@salesforce/afv-skills 1.43.0 → 1.45.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/consumer-goods-rtr-datacloud-export-configure/SKILL.md +72 -0
- package/skills/consumer-goods-rtr-datacloud-export-configure/references/inputs-and-namespace.md +38 -0
- package/skills/consumer-goods-rtr-datacloud-export-configure/references/procedure.md +158 -0
- package/skills/consumer-goods-rtr-datacloud-export-configure/scripts/detect-namespace.js +86 -0
- package/skills/consumer-goods-rtr-datacloud-export-configure/scripts/render-apex.js +64 -0
- package/skills/consumer-goods-rtr-datacloud-export-configure/scripts/resolve-id-by-name.js +47 -0
- package/skills/consumer-goods-rtr-datacloud-export-configure/scripts/sf-rest.js +171 -0
- package/skills/consumer-goods-rtr-datacloud-export-configure/scripts/soql-escape.js +26 -0
- package/skills/consumer-goods-rtr-datacloud-export-configure/scripts/upsert-report-config.apex +51 -0
- package/skills/consumer-goods-rtr-datacloud-export-configure/scripts/upsert-system-setting.apex +21 -0
- package/skills/consumer-goods-tpe-dashboard-configure/SKILL.md +74 -0
- package/skills/consumer-goods-tpe-dashboard-configure/references/phases-1-6.md +112 -0
- package/skills/consumer-goods-tpe-dashboard-configure/references/phases-7-12.md +157 -0
- package/skills/consumer-goods-tpe-dashboard-configure/scripts/find-failure-reason.js +132 -0
- package/skills/consumer-goods-tpe-dashboard-configure/scripts/poll-status.js +116 -0
- package/skills/consumer-goods-tpe-dashboard-configure/scripts/render-apex.js +64 -0
- package/skills/consumer-goods-tpe-dashboard-configure/scripts/run-data-transform.js +121 -0
- package/skills/consumer-goods-tpe-dashboard-configure/scripts/schedule-business-period-export.apex +27 -0
- package/skills/consumer-goods-tpe-dashboard-configure/scripts/sf-rest.js +171 -0
- package/skills/consumer-goods-tpe-dashboard-configure/scripts/soql-escape.js +25 -0
- package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/SKILL.md +141 -0
- package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/references/payload-shapes.md +447 -0
- package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/references/procedure.md +263 -0
- package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/scripts/clone-tpe-dashboards.js +537 -0
- package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/scripts/sf-rest.js +195 -0
- package/skills/consumer-goods-tpe-datakit-deploy/SKILL.md +157 -0
- package/skills/consumer-goods-tpe-datakit-deploy/scripts/detect-namespace.js +86 -0
- package/skills/consumer-goods-tpe-datakit-deploy/scripts/download-static-resource.js +151 -0
- package/skills/consumer-goods-tpe-datakit-deploy/scripts/extract-crm-field-permissions.js +115 -0
- package/skills/consumer-goods-tpe-datakit-deploy/scripts/sf-rest.js +109 -0
- package/skills/consumer-goods-tpe-datakit-deploy/scripts/update-field-permissions.js +433 -0
- package/skills/experience-cms-content-generate/SKILL.md +2 -0
- package/skills/service-catalog-template-coordinate/SKILL.md +263 -0
- package/skills/service-catalog-template-coordinate/examples/output-templates.md +44 -0
- package/skills/service-catalog-template-coordinate/references/mcp-invocation.md +183 -0
- package/skills/service-catalog-template-coordinate/references/operations.md +230 -0
- package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/SKILL.md +243 -0
- package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/references/cli-invocation.md +205 -0
- package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/references/helper-contracts.md +236 -0
- package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/references/permset-topology.md +132 -0
- package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/scripts/classify-activated-agents.mjs +106 -0
- package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/scripts/classify-agent-access-state.mjs +113 -0
- package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/scripts/classify-assignment-state.mjs +99 -0
- package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/scripts/classify-platform-permset-availability.mjs +155 -0
- package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/scripts/gate-unified-catalog-tiers.mjs +100 -0
- package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/scripts/rank-candidate-users.mjs +95 -0
- package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/scripts/resolve-target-user.mjs +86 -0
- package/skills/service-itsm-agentic-setup-agentforce-coordinate/SKILL.md +44 -23
- package/skills/service-itsm-agentic-setup-agentforce-coordinate/examples/output-templates.md +33 -9
- package/skills/service-itsm-agentic-setup-agentforce-studio-configure/SKILL.md +17 -18
- package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +3 -1
- package/skills/service-itsm-agentic-setup-configure/SKILL.md +20 -12
- package/skills/service-itsm-agentic-setup-configure/examples/output-templates.md +73 -5
- package/skills/service-itsm-agentic-setup-employee-agent-configure/SKILL.md +8 -7
- package/skills/service-itsm-agentic-setup-employee-agent-configure/references/cli-invocation.md +45 -33
- package/skills/service-itsm-agentic-setup-employee-agent-configure/references/reactivation.md +8 -6
- package/skills/service-itsm-agentic-setup-employee-agent-configure/references/workflow-detail.md +10 -10
- package/skills/service-itsm-agentic-setup-employee-agent-configure/scripts/classify-agent-existence.mjs +114 -56
- package/skills/service-itsm-agentic-setup-employee-agent-configure/scripts/classify-preflight.mjs +33 -17
- package/skills/service-itsm-agentic-setup-employee-agent-configure/scripts/render-report.mjs +9 -3
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/SKILL.md +8 -7
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/cli-invocation.md +43 -32
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/reactivation.md +6 -4
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/workflow-detail.md +10 -10
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/classify-agent-existence.mjs +106 -55
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/classify-preflight.mjs +27 -13
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/render-report.mjs +9 -3
- package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +159 -161
- package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/attach-milestone-action.json +51 -0
- package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/attach-milestone.json +1 -1
- package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/predefined-incident-policy.json +120 -0
- package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/milestone-patterns.md +28 -5
- package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/output-templates.md +19 -1
- package/skills/service-itsm-agentic-setup-incident-sla-configure/references/mcp-invocation.md +350 -30
- package/skills/service-itsm-channels-coordinate/SKILL.md +80 -213
- package/skills/service-itsm-slack-itservice-configure/SKILL.md +363 -0
- package/skills/service-itsm-slack-itservice-configure/references/connect-agentforce-to-slack.md +159 -0
- package/skills/service-itsm-slack-itservice-configure/references/manage-slack-connection.md +88 -0
- package/skills/service-itsm-slack-itservice-configure/references/manage-user-access.md +117 -0
- package/skills/service-itsm-slack-itservice-configure/references/record-visibility.md +78 -0
- package/skills/service-itsm-slack-itservice-configure/references/site-membership-verification.md +126 -0
- package/skills/service-itsm-slack-itservice-configure/scripts/classify-user-access.mjs +167 -0
- package/skills/service-itsm-teams-configure/SKILL.md +50 -47
- package/skills/service-itsm-teams-configure/references/azure-credential-population.md +42 -28
- package/skills/service-itsm-teams-configure/references/gotchas.md +1 -2
- package/skills/service-itsm-teams-coordinate/SKILL.md +22 -18
- package/skills/service-itsm-teams-coordinate/examples/output-templates.md +12 -9
- package/skills/service-itsm-teams-itdesk-configure/SKILL.md +60 -44
- package/skills/service-itsm-teams-itservice-configure/SKILL.md +56 -70
- package/skills/service-catalog-template-deploy/SKILL.md +0 -310
- package/skills/service-catalog-template-deploy/references/cli-invocation.md +0 -258
- package/skills/service-catalog-template-deploy/scripts/activate-verify.mjs +0 -164
- package/skills/service-catalog-template-deploy/scripts/build-deploy-payload.mjs +0 -94
- package/skills/service-catalog-template-deploy/scripts/resolve-template.mjs +0 -331
- package/skills/service-catalog-template-search/SKILL.md +0 -212
- package/skills/service-catalog-template-search/references/cli-invocation.md +0 -128
- package/skills/service-catalog-template-search/scripts/classify-catalog.mjs +0 -205
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# Full procedure
|
|
2
|
+
|
|
3
|
+
Implements Salesforce Help's "Customize Trade Promotion Effectiveness Analytics Dashboards" —
|
|
4
|
+
Customization Scenario 1 ("Use Custom KPIs with Standard Dashboards") — headlessly, driven entirely
|
|
5
|
+
by `sf` CLI + REST against an already-authenticated org.
|
|
6
|
+
|
|
7
|
+
## Namespace detection (run once, before Phase 0)
|
|
8
|
+
|
|
9
|
+
Same canonical procedure as sibling skills — never assume a namespace:
|
|
10
|
+
|
|
11
|
+
1. ```bash
|
|
12
|
+
sf package installed list --target-org <username> --json
|
|
13
|
+
```
|
|
14
|
+
Find the entry with `SubscriberPackageName == "Consumer Goods Cloud"`. If found, `NS` = its
|
|
15
|
+
`SubscriberPackageNamespace`.
|
|
16
|
+
2. If no package is found inform the user and stop the process.
|
|
17
|
+
|
|
18
|
+
The REST paths used throughout this skill are all standard platform paths under
|
|
19
|
+
`/services/data/...` — **never namespaced**, regardless of `NS`. Namespace detection is still run
|
|
20
|
+
for consistency with sibling skills and in case a future phase needs `NS_FIELD`; do not apply `NS`
|
|
21
|
+
to any `/services/data/...` path below.
|
|
22
|
+
|
|
23
|
+
## Phase 0 — Preflight & discovery
|
|
24
|
+
|
|
25
|
+
1. Verify org connectivity and run namespace detection.
|
|
26
|
+
2. **API version is pinned to `v67.0` for every `/services/data/...` call below — per standing
|
|
27
|
+
instruction, do not resolve it from the org's own `apiVersion`.** (Historical note: `v64.0` was
|
|
28
|
+
found to return `DOWNGRADE_VERSION_ERROR` on visualization GETs — so if `v67.0` ever regresses
|
|
29
|
+
similarly in a given org, surface the error rather than silently falling back to a different
|
|
30
|
+
version.)
|
|
31
|
+
3. **Resolve real artifact ids by walking the installed app's asset list — never hardcode an id or
|
|
32
|
+
api-name across orgs.**
|
|
33
|
+
```bash
|
|
34
|
+
node ./scripts/sf-rest.js --target-org <username> \
|
|
35
|
+
--path "/services/data/<apiVersion>/app-framework/apps?templateSourceId=sfdc_internal__Trade_Promotion_Effectiveness"
|
|
36
|
+
```
|
|
37
|
+
Not present, or no entry with `applicationStatus` in `SuccessStatus`/`SuccessWithWarningsStatus`
|
|
38
|
+
⇒ **block**, point the user to `consumer-goods-tpe-dashboard-configure` to install prerequisites
|
|
39
|
+
first.
|
|
40
|
+
**If more than one entry matches** — never silently pick the first, the newest, or any other
|
|
41
|
+
guessed tie-break. List every matching candidate's `id`, `name`/`label`, and `createdDate` and
|
|
42
|
+
**stop and ask the user which app install to target**. Only continue automatically when exactly
|
|
43
|
+
one `SuccessStatus`/`SuccessWithWarningsStatus` entry matches. Otherwise take that app's `id` and
|
|
44
|
+
GET its asset list:
|
|
45
|
+
```bash
|
|
46
|
+
node ./scripts/sf-rest.js --target-org <username> \
|
|
47
|
+
--path "/services/data/<apiVersion>/app-framework/apps/<appId>/assets"
|
|
48
|
+
```
|
|
49
|
+
From the returned `assets[]`, resolve by `type`/`templateAssetSourceName`:
|
|
50
|
+
- `type: "SemanticModel"`, `templateAssetSourceName` starting with `Extended_Trade_Promotion_Management` → the Extended TPM Analytics model's `assetIdOrName`.
|
|
51
|
+
- `type: "Dashboard"`, `templateAssetSourceName` == `PromotionAnalysis` / `TacticAnalysis` → each base dashboard's `assetIdOrName`.
|
|
52
|
+
- `type: "Visualization"` entries → every base visualization's `assetIdOrName`; identify which
|
|
53
|
+
ones the two dashboards actually use in step 5 below.
|
|
54
|
+
If the Extended model or either dashboard asset is missing ⇒ **block**, point to
|
|
55
|
+
`consumer-goods-tpe-dashboard-configure`.
|
|
56
|
+
4. **GET the Extended model — the whole model in one call, no working single-parameter GET
|
|
57
|
+
confirmed:**
|
|
58
|
+
```bash
|
|
59
|
+
node ./scripts/sf-rest.js --target-org <username> \
|
|
60
|
+
--path "/services/data/<apiVersion>/ssot/semantic/models/<extendedModelId>"
|
|
61
|
+
```
|
|
62
|
+
Index into `semanticParameters[]` and `semanticCalculatedMeasurements[]` by `apiName` to find all
|
|
63
|
+
5 slots' parameter + calculated-measurement pairs — see `references/payload-shapes.md` for the
|
|
64
|
+
confirmed apiNames and full JSON shape of both artifact types.
|
|
65
|
+
5. GET each base dashboard selected during Inputs collection, and every base visualization its
|
|
66
|
+
`widgets[].source` (type `"visualization"`) points at:
|
|
67
|
+
```bash
|
|
68
|
+
node ./scripts/sf-rest.js --target-org <username> \
|
|
69
|
+
--path "/services/data/<apiVersion>/tableau/dashboards/<baseDashboardId>"
|
|
70
|
+
node ./scripts/sf-rest.js --target-org <username> \
|
|
71
|
+
--path "/services/data/<apiVersion>/tableau/visualizations/<baseVizId>"
|
|
72
|
+
```
|
|
73
|
+
6. Field shapes for parameters, calculated measurements, visualizations, and dashboard widgets are
|
|
74
|
+
already documented in `references/payload-shapes.md` — use that file directly, no need to
|
|
75
|
+
re-derive it from this org's live response. Only revisit it if a future package/template
|
|
76
|
+
version changes these shapes.
|
|
77
|
+
7. Report Phase 0 pass/blocked, including the resolved apiVersion, model id, dashboard ids, and
|
|
78
|
+
visualization ids.
|
|
79
|
+
|
|
80
|
+
## Phase 1 — Resolve the 5-slot plan
|
|
81
|
+
|
|
82
|
+
For each of the 5 known slots (Promotion Measure 1-3, Tactic Measure 1-2), using the real base
|
|
83
|
+
parameter + calculated-measurement JSON captured in Phase 0:
|
|
84
|
+
|
|
85
|
+
- If the customer supplied an override (always a full `{measureCode, displayName}` array collected
|
|
86
|
+
during Inputs — a single-pair answer is still an array of length 1):
|
|
87
|
+
- The new parameter = deep copy of the base parameter with `apiName` suffixed, `allowedValues`
|
|
88
|
+
**replaced entirely** by the customer's array (each entry mapped to `{displayName, value:
|
|
89
|
+
measureCode}` — base entries are discarded, not merged), and `defaultValue` set to the
|
|
90
|
+
customer-specified default, or the first entry's `displayName` if none was specified. This is
|
|
91
|
+
REPLACE mode (see Phases 2-4 below) — the customer's list is the whole menu, not a patch to it.
|
|
92
|
+
- The new calculated measurement = deep copy of the base measurement with `apiName` suffixed and
|
|
93
|
+
`expression` rewritten to reference the new parameter's suffixed `apiName` in place of the base
|
|
94
|
+
one (`[Parameters].[<baseParamApiName>]` → `[Parameters].[<newParamApiName>]`).
|
|
95
|
+
- If no override was supplied: both the new parameter and new calculated measurement are exact
|
|
96
|
+
deep copies of the base ones, with only `apiName` suffixed (and the measurement's `expression`
|
|
97
|
+
still repointed at the sibling clone's new parameter `apiName`).
|
|
98
|
+
|
|
99
|
+
Print the resolved plan — slot → new parameter apiName → new measurement apiName → source
|
|
100
|
+
(override / base-copy) → resolved KPI (existing-entry / newly-appended) → values — and get explicit
|
|
101
|
+
confirmation before Phase 2 writes anything.
|
|
102
|
+
|
|
103
|
+
## Phases 2-4 — Clone parameters, measurements, visualizations, and dashboards
|
|
104
|
+
|
|
105
|
+
**Confirmed live and implemented by `scripts/clone-tpe-dashboards.js`** — a deterministic Node
|
|
106
|
+
driver that runs Phases 2-4 in one process. Prefer running it over hand-rolling the individual
|
|
107
|
+
`sf-rest.js` calls below; use the manual calls only for one-off debugging or to inspect a single
|
|
108
|
+
artifact.
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
node ./scripts/clone-tpe-dashboards.js --target-org <username> --suffix <Suffix> \
|
|
112
|
+
[--overrides '{"Promotion_Measure_1":{"measureCode":"VOLU","displayName":"Volume"}}'] \
|
|
113
|
+
[--max-vizs-per-dashboard N] [--dry-run]
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
`--overrides` supports two modes per slot, resolved by `slotOverride()` in the script:
|
|
117
|
+
|
|
118
|
+
- **APPEND mode** — `{"measureCode":"TARE","displayName":"My Custom KPI Name"}`. The customer's
|
|
119
|
+
entry is upserted into the base's full `allowedValues` list by `value` (the measure code): if the
|
|
120
|
+
code already exists in the base menu, its `displayName` is replaced in place (count stays the
|
|
121
|
+
same); if it's a new code, it's appended (count grows by one). `defaultValue` is set to the
|
|
122
|
+
resolved `displayName`. Confirmed live with suffix `Cust6`/`Dbg2`: overriding an existing code
|
|
123
|
+
with a new display name leaves `allowedValues` count unchanged with exactly one entry for that
|
|
124
|
+
code; overriding with a brand-new code grows the count by one.
|
|
125
|
+
- **REPLACE mode** — `{"allowedValues":[{"displayName":"...","value":"..."}, ...],
|
|
126
|
+
"defaultValue":"..."}` (optional `defaultValue`; defaults to the first entry's `displayName` if
|
|
127
|
+
omitted). The customer supplies the *complete* menu for that slot; base entries are discarded
|
|
128
|
+
entirely rather than merged. `defaultValue` must match one of the supplied `displayName`s or the
|
|
129
|
+
script throws before any writes happen.
|
|
130
|
+
|
|
131
|
+
A slot omitted from `--overrides` still gets a full clone via APPEND mode with no changes (base
|
|
132
|
+
measure code, base display name + suffix, full base `allowedValues` untouched).
|
|
133
|
+
|
|
134
|
+
**Inputs collection (above) always produces REPLACE-mode overrides** — the customer's array
|
|
135
|
+
replaces menu entries wholesale, per slot. APPEND mode still exists in the script and stays
|
|
136
|
+
available for hand-rolled/debug runs where only a single `{measureCode, displayName}` patch onto
|
|
137
|
+
the base menu is wanted, but the standard interactive flow never emits it.
|
|
138
|
+
|
|
139
|
+
**Both dashboards (Promotion + Tactic) are always cloned, regardless of which slots have
|
|
140
|
+
overrides** — `DASHBOARDS` in the script is a fixed constant, not derived from the override keys or
|
|
141
|
+
any selection input. There is currently no flag to clone only one dashboard.
|
|
142
|
+
|
|
143
|
+
`--max-vizs-per-dashboard N` is a **debug/iteration aid only** — caps how many distinct
|
|
144
|
+
visualizations get cloned per dashboard so a validation pass doesn't have to wait through all 9
|
|
145
|
+
(Promotion) / 7 (Tactic) real viz clones every time. Widgets beyond the cap are left pointing at
|
|
146
|
+
their base visualization — the dashboard still builds, just without full viz coverage. **Never use
|
|
147
|
+
this flag for an actual customer deliverable** — omit it for a real/complete run.
|
|
148
|
+
|
|
149
|
+
It resolves the app/assets/model exactly as Phase 0 describes, resolves both slots' calculated
|
|
150
|
+
measurements dynamically (never assuming `_value`-vs-`_clc` naming by symmetry), builds and prints
|
|
151
|
+
the Phase 1 plan, and — unless `--dry-run` — POSTs all 5 parameters, 5 measurements, every
|
|
152
|
+
visualization on either dashboard that references one of the 5 slot measurements, and both
|
|
153
|
+
dashboards, in the correct dependency order. See its header comment and
|
|
154
|
+
`references/payload-shapes.md` for the exact confirmed request-body shapes per endpoint.
|
|
155
|
+
|
|
156
|
+
### Real-write findings baked into the script (see `references/payload-shapes.md` for the full trace)
|
|
157
|
+
|
|
158
|
+
- **A cloned parameter's and measurement's `label` must be suffixed too, not just `apiName`** —
|
|
159
|
+
`label` is uniqueness-checked; reusing the base label across enough clones fails with
|
|
160
|
+
`CREATE_SEMANTIC_ENTITY_FAILED`.
|
|
161
|
+
- **The visualization POST body's `dataSource` ref must keep its `.type`** — the dashboard-only rule
|
|
162
|
+
of stripping `.label`/`.type` from `Visualization`/`SemanticModel`-typed ref objects does **not**
|
|
163
|
+
apply to a visualization's own body; applying it there strips `dataSource.type` and fails with
|
|
164
|
+
`INVALID_INPUT: "Value required for [type]."`
|
|
165
|
+
- **Every visualization on a dashboard that references a slot measurement must be cloned — not just
|
|
166
|
+
one "designated" viz per dashboard.** Confirmed live, **all 9** visualization widgets on
|
|
167
|
+
`PromotionAnalysis1` and **all 7** on `TacticAnalysis1` reference at least one of the 5 slot
|
|
168
|
+
measurements — top/bottom performers, trend charts, category/product breakdowns, not just the one
|
|
169
|
+
obviously-named chart. The script discovers every `visualization`-type widget on the base
|
|
170
|
+
dashboard directly and clones any whose viz JSON contains a slot measurement apiName; a viz with
|
|
171
|
+
no such reference is correctly left pointing at base.
|
|
172
|
+
- **A cloned visualization's cosmetic `fields[].label` text embeds the base parameter's *label*, not
|
|
173
|
+
its apiName** (e.g. `<[Parameters].[Promotion Measure 1]>`), so an apiName-only replace never
|
|
174
|
+
touches it. The script also suffixes each parameter's label and replaces the exact
|
|
175
|
+
`[Parameters].[<label>]` bracket pattern in every cloned visualization and dashboard body.
|
|
176
|
+
- **APPEND-mode overrides must upsert by measure code, not blindly push** — the script filters out
|
|
177
|
+
any existing entry with the same `value` before appending the resolved entry, so reusing an
|
|
178
|
+
existing measure code with a new display name produces exactly one entry for that code.
|
|
179
|
+
|
|
180
|
+
### Hand-rolling a single step (debug only)
|
|
181
|
+
|
|
182
|
+
If you must hand-roll a single step instead of running the script, the endpoints are:
|
|
183
|
+
`POST /services/data/<apiVersion>/ssot/semantic/models/<extendedModelApiName>/parameters`,
|
|
184
|
+
`POST /services/data/<apiVersion>/ssot/semantic/models/<extendedModelApiName>/calculated-measurements`,
|
|
185
|
+
`POST /services/data/<apiVersion>/tableau/visualizations`,
|
|
186
|
+
`POST /services/data/<apiVersion>/tableau/dashboards` — in that dependency order (parameter before
|
|
187
|
+
its measurement; both before any visualization that references the measurement; every affected
|
|
188
|
+
visualization before the dashboard that references it). Capture every new artifact's id/apiName,
|
|
189
|
+
keyed by slot (parameters/measurements) or base name (visualizations). This always produces 5 new
|
|
190
|
+
parameters + 5 new measurements — never fewer — regardless of how many slots have an actual
|
|
191
|
+
override, and a new visualization for **every** dashboard widget that referenced a slot
|
|
192
|
+
measurement, not a fixed count. Record pass/blocked per slot/artifact.
|
|
193
|
+
|
|
194
|
+
Re-running with a suffix that's already been used in that model **will fail** on the parameters
|
|
195
|
+
POST with `CREATE_SEMANTIC_ENTITY_FAILED` (apiName uniqueness is enforced) — always confirm the
|
|
196
|
+
chosen suffix hasn't been used before, or delete the prior clone set first.
|
|
197
|
+
|
|
198
|
+
## Phase 5 — Verify
|
|
199
|
+
|
|
200
|
+
GET every created parameter, calculated measurement, visualization, and dashboard back:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
node ./scripts/sf-rest.js --target-org <username> \
|
|
204
|
+
--path "/services/data/<apiVersion>/ssot/semantic/models/<extendedModelId>"
|
|
205
|
+
node ./scripts/sf-rest.js --target-org <username> \
|
|
206
|
+
--path "/services/data/<apiVersion>/tableau/visualizations/<newVizId>"
|
|
207
|
+
node ./scripts/sf-rest.js --target-org <username> \
|
|
208
|
+
--path "/services/data/<apiVersion>/tableau/dashboards/<newDashboardId>"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
(Parameters/measurements are read back via the same whole-model GET as Phase 0 — index into
|
|
212
|
+
`semanticParameters[]`/`semanticCalculatedMeasurements[]` by the new suffixed apiNames.) Confirm
|
|
213
|
+
each new parameter resolves to the intended override (or exactly matches its base counterpart's
|
|
214
|
+
values, for un-overridden slots), each new measurement's `expression` references the new parameter
|
|
215
|
+
apiName (never a base one), each visualization references the correct new measurement apiName(s)
|
|
216
|
+
everywhere they appear, and each dashboard's widgets reference the correct new visualization(s) and
|
|
217
|
+
parameter(s). Record pass/blocked per artifact for the final report.
|
|
218
|
+
|
|
219
|
+
## Rules
|
|
220
|
+
|
|
221
|
+
- Never authenticate on the user's behalf — if `org-status` shows disconnected, stop and ask
|
|
222
|
+
the user to log in themselves.
|
|
223
|
+
- Never run `sf org display --json` directly and read its output — always go through
|
|
224
|
+
`scripts/sf-rest.js`'s `org-status` subcommand, which strips `accessToken` before printing.
|
|
225
|
+
- Never mutate a base-model parameter, calculated measurement, visualization, or dashboard — every
|
|
226
|
+
write in this skill is a new POST of a suffixed copy. Never PATCH a base artifact.
|
|
227
|
+
- Never create a new parameter/measurement/visualization/dashboard without an explicit user
|
|
228
|
+
go-ahead on the Phase 1 resolved plan first.
|
|
229
|
+
- Always produce all 5 slots' worth of clones (parameter + calculated measurement = 10 artifacts),
|
|
230
|
+
even when 0 slots have an override — an unmentioned slot's new parameter/measurement must still
|
|
231
|
+
be created as copies of its base counterparts, never skipped or left pointing at base artifacts.
|
|
232
|
+
- Never leave a cloned calculated measurement's `expression` referencing a base parameter apiName —
|
|
233
|
+
once a parameter is cloned, every measurement that used it must be repointed at the clone.
|
|
234
|
+
- Always use API version `v67.0` for every `/services/data/...` call — pinned per standing
|
|
235
|
+
instruction, not resolved from the target org's own `apiVersion`.
|
|
236
|
+
- Never hardcode an artifact id or api-name across orgs — resolve them per-org via the installed
|
|
237
|
+
app's `assetUrl`/`assets[]` (Phase 0), never assume ids confirmed on one org apply elsewhere.
|
|
238
|
+
- Never guess a JSON field name for a measure-code binding or a parameter/visualization/dashboard
|
|
239
|
+
reference — Phase 0's live-captured payload shapes are the only source of truth; if a needed
|
|
240
|
+
field can't be identified from a real response, stop and ask the user rather than writing a
|
|
241
|
+
guessed payload.
|
|
242
|
+
- Never hardcode the namespace in a REST path — `/services/data/...` paths in this skill are never
|
|
243
|
+
namespaced regardless of `NS`.
|
|
244
|
+
- Never reuse a base-model API name for a new artifact — always apply the customer's suffix.
|
|
245
|
+
- Never assume only one "designated" visualization per dashboard needs cloning — discover every
|
|
246
|
+
`visualization`-type widget on the base dashboard and clone any whose viz references a slot
|
|
247
|
+
measurement; confirmed live, that is every visualization widget on both TPE dashboards.
|
|
248
|
+
- A poll timeout or a transient discovery gap is not a failure — report it as blocked/pending with
|
|
249
|
+
the specific reason, not as a guessed success.
|
|
250
|
+
|
|
251
|
+
## Report
|
|
252
|
+
|
|
253
|
+
At the end of a run, give the user a structured status per phase (0-5): pass / blocked / pending,
|
|
254
|
+
with the specific blocking reason where applicable, and the final list of created artifacts (slot →
|
|
255
|
+
new parameter, base viz → new viz, base dashboard → new dashboard). Call out anything skipped due
|
|
256
|
+
to dry-run or a declined confirmation.
|
|
257
|
+
|
|
258
|
+
**When invoked via delegation** (the calling skill used the `Skill` tool to reach this file, rather
|
|
259
|
+
than the user directly — e.g. `consumer-goods-tpe-dashboard-configure`'s customization step): this
|
|
260
|
+
report is an intermediate result, not the end of the task. Return it to the calling skill and let it
|
|
261
|
+
continue with its own next phase (or finish its own overall report) — do not present this report to
|
|
262
|
+
the user as the final answer and stop. Only surface this report directly to the user when this
|
|
263
|
+
skill was invoked standalone.
|