@salesforce/afv-skills 1.44.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.
Files changed (97) hide show
  1. package/package.json +1 -1
  2. package/skills/consumer-goods-rtr-datacloud-export-configure/SKILL.md +72 -0
  3. package/skills/consumer-goods-rtr-datacloud-export-configure/references/inputs-and-namespace.md +38 -0
  4. package/skills/consumer-goods-rtr-datacloud-export-configure/references/procedure.md +158 -0
  5. package/skills/consumer-goods-rtr-datacloud-export-configure/scripts/detect-namespace.js +86 -0
  6. package/skills/consumer-goods-rtr-datacloud-export-configure/scripts/render-apex.js +64 -0
  7. package/skills/consumer-goods-rtr-datacloud-export-configure/scripts/resolve-id-by-name.js +47 -0
  8. package/skills/consumer-goods-rtr-datacloud-export-configure/scripts/sf-rest.js +171 -0
  9. package/skills/consumer-goods-rtr-datacloud-export-configure/scripts/soql-escape.js +26 -0
  10. package/skills/consumer-goods-rtr-datacloud-export-configure/scripts/upsert-report-config.apex +51 -0
  11. package/skills/consumer-goods-rtr-datacloud-export-configure/scripts/upsert-system-setting.apex +21 -0
  12. package/skills/consumer-goods-tpe-dashboard-configure/SKILL.md +74 -0
  13. package/skills/consumer-goods-tpe-dashboard-configure/references/phases-1-6.md +112 -0
  14. package/skills/consumer-goods-tpe-dashboard-configure/references/phases-7-12.md +157 -0
  15. package/skills/consumer-goods-tpe-dashboard-configure/scripts/find-failure-reason.js +132 -0
  16. package/skills/consumer-goods-tpe-dashboard-configure/scripts/poll-status.js +116 -0
  17. package/skills/consumer-goods-tpe-dashboard-configure/scripts/render-apex.js +64 -0
  18. package/skills/consumer-goods-tpe-dashboard-configure/scripts/run-data-transform.js +121 -0
  19. package/skills/consumer-goods-tpe-dashboard-configure/scripts/schedule-business-period-export.apex +27 -0
  20. package/skills/consumer-goods-tpe-dashboard-configure/scripts/sf-rest.js +171 -0
  21. package/skills/consumer-goods-tpe-dashboard-configure/scripts/soql-escape.js +25 -0
  22. package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/SKILL.md +141 -0
  23. package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/references/payload-shapes.md +447 -0
  24. package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/references/procedure.md +263 -0
  25. package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/scripts/clone-tpe-dashboards.js +537 -0
  26. package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/scripts/sf-rest.js +195 -0
  27. package/skills/consumer-goods-tpe-datakit-deploy/SKILL.md +157 -0
  28. package/skills/consumer-goods-tpe-datakit-deploy/scripts/detect-namespace.js +86 -0
  29. package/skills/consumer-goods-tpe-datakit-deploy/scripts/download-static-resource.js +151 -0
  30. package/skills/consumer-goods-tpe-datakit-deploy/scripts/extract-crm-field-permissions.js +115 -0
  31. package/skills/consumer-goods-tpe-datakit-deploy/scripts/sf-rest.js +109 -0
  32. package/skills/consumer-goods-tpe-datakit-deploy/scripts/update-field-permissions.js +433 -0
  33. package/skills/service-catalog-template-coordinate/SKILL.md +263 -0
  34. package/skills/service-catalog-template-coordinate/examples/output-templates.md +44 -0
  35. package/skills/service-catalog-template-coordinate/references/mcp-invocation.md +183 -0
  36. package/skills/service-catalog-template-coordinate/references/operations.md +230 -0
  37. package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/SKILL.md +243 -0
  38. package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/references/cli-invocation.md +205 -0
  39. package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/references/helper-contracts.md +236 -0
  40. package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/references/permset-topology.md +132 -0
  41. package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/scripts/classify-activated-agents.mjs +106 -0
  42. package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/scripts/classify-agent-access-state.mjs +113 -0
  43. package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/scripts/classify-assignment-state.mjs +99 -0
  44. package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/scripts/classify-platform-permset-availability.mjs +155 -0
  45. package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/scripts/gate-unified-catalog-tiers.mjs +100 -0
  46. package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/scripts/rank-candidate-users.mjs +95 -0
  47. package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/scripts/resolve-target-user.mjs +86 -0
  48. package/skills/service-itsm-agentic-setup-agentforce-coordinate/SKILL.md +44 -23
  49. package/skills/service-itsm-agentic-setup-agentforce-coordinate/examples/output-templates.md +33 -9
  50. package/skills/service-itsm-agentic-setup-agentforce-studio-configure/SKILL.md +17 -18
  51. package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +3 -1
  52. package/skills/service-itsm-agentic-setup-configure/SKILL.md +20 -12
  53. package/skills/service-itsm-agentic-setup-configure/examples/output-templates.md +73 -5
  54. package/skills/service-itsm-agentic-setup-employee-agent-configure/SKILL.md +8 -7
  55. package/skills/service-itsm-agentic-setup-employee-agent-configure/references/cli-invocation.md +45 -33
  56. package/skills/service-itsm-agentic-setup-employee-agent-configure/references/reactivation.md +8 -6
  57. package/skills/service-itsm-agentic-setup-employee-agent-configure/references/workflow-detail.md +10 -10
  58. package/skills/service-itsm-agentic-setup-employee-agent-configure/scripts/classify-agent-existence.mjs +114 -56
  59. package/skills/service-itsm-agentic-setup-employee-agent-configure/scripts/classify-preflight.mjs +33 -17
  60. package/skills/service-itsm-agentic-setup-employee-agent-configure/scripts/render-report.mjs +9 -3
  61. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/SKILL.md +8 -7
  62. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/cli-invocation.md +43 -32
  63. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/reactivation.md +6 -4
  64. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/workflow-detail.md +10 -10
  65. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/classify-agent-existence.mjs +106 -55
  66. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/classify-preflight.mjs +27 -13
  67. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/render-report.mjs +9 -3
  68. package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +159 -161
  69. package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/attach-milestone-action.json +51 -0
  70. package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/attach-milestone.json +1 -1
  71. package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/predefined-incident-policy.json +120 -0
  72. package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/milestone-patterns.md +28 -5
  73. package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/output-templates.md +19 -1
  74. package/skills/service-itsm-agentic-setup-incident-sla-configure/references/mcp-invocation.md +350 -30
  75. package/skills/service-itsm-channels-coordinate/SKILL.md +80 -213
  76. package/skills/service-itsm-slack-itservice-configure/SKILL.md +363 -0
  77. package/skills/service-itsm-slack-itservice-configure/references/connect-agentforce-to-slack.md +159 -0
  78. package/skills/service-itsm-slack-itservice-configure/references/manage-slack-connection.md +88 -0
  79. package/skills/service-itsm-slack-itservice-configure/references/manage-user-access.md +117 -0
  80. package/skills/service-itsm-slack-itservice-configure/references/record-visibility.md +78 -0
  81. package/skills/service-itsm-slack-itservice-configure/references/site-membership-verification.md +126 -0
  82. package/skills/service-itsm-slack-itservice-configure/scripts/classify-user-access.mjs +167 -0
  83. package/skills/service-itsm-teams-configure/SKILL.md +50 -47
  84. package/skills/service-itsm-teams-configure/references/azure-credential-population.md +42 -28
  85. package/skills/service-itsm-teams-configure/references/gotchas.md +1 -2
  86. package/skills/service-itsm-teams-coordinate/SKILL.md +22 -18
  87. package/skills/service-itsm-teams-coordinate/examples/output-templates.md +12 -9
  88. package/skills/service-itsm-teams-itdesk-configure/SKILL.md +60 -44
  89. package/skills/service-itsm-teams-itservice-configure/SKILL.md +56 -70
  90. package/skills/service-catalog-template-deploy/SKILL.md +0 -310
  91. package/skills/service-catalog-template-deploy/references/cli-invocation.md +0 -258
  92. package/skills/service-catalog-template-deploy/scripts/activate-verify.mjs +0 -164
  93. package/skills/service-catalog-template-deploy/scripts/build-deploy-payload.mjs +0 -94
  94. package/skills/service-catalog-template-deploy/scripts/resolve-template.mjs +0 -331
  95. package/skills/service-catalog-template-search/SKILL.md +0 -212
  96. package/skills/service-catalog-template-search/references/cli-invocation.md +0 -128
  97. package/skills/service-catalog-template-search/scripts/classify-catalog.mjs +0 -205
@@ -13,6 +13,24 @@ exposes four meta-tools:
13
13
  signs the request with the JWT bound to the current MCP session and forwards it to the org. The
14
14
  skill never handles credentials or an org alias — everything is derived from the session.
15
15
 
16
+ ## Contents
17
+
18
+ - [Response envelope](#response-envelope)
19
+ - [Routes](#routes)
20
+ - [Phase 0.5 — SLA Management for IT Service prerequisite gate](#phase-05--sla-management-for-it-service-prerequisite-gate)
21
+ - [Discovery — always run first](#discovery--always-run-first)
22
+ - [Preflight A — Master Incident Management pref (direct read)](#preflight-a--master-incident-management-pref-direct-read)
23
+ - [Preflight B — SLA fields on the Incident sObject](#preflight-b--sla-fields-on-the-incident-sobject)
24
+ - [Default BusinessHours](#default-businesshours)
25
+ - [Create MilestoneType](#create-milestonetype)
26
+ - [Create SLA Policy (SlaProcess)](#create-sla-policy-slaprocess)
27
+ - [Attach Milestone](#attach-milestone)
28
+ - [Milestone Actions (Phase 2.5 — Warn / Escalate)](#milestone-actions-phase-25--warn--escalate)
29
+ - [Create Entitlement (standard sObject)](#create-entitlement-standard-sobject)
30
+ - [Predefined Incident Policy (Phase 0.6 detect + Phase 2-OOB seed)](#predefined-incident-policy-phase-06-detect--phase-2-oob-seed)
31
+ - [Verify SLA engagement](#verify-sla-engagement)
32
+ - [Gotchas](#gotchas)
33
+
16
34
  ## Response envelope
17
35
 
18
36
  The SLA Management Connect API, `/sobjects/…` REST endpoints, and `/query` are **standard REST** —
@@ -37,11 +55,15 @@ this skill uses none.)
37
55
  | `PATCH /services/data/v67.0/tooling/sobjects/EntitlementSettings/000000000000000AAA` | Phase 0.5 — turn on SLA Versioning if off |
38
56
  | `GET /services/data/v67.0/sobjects/Incident/describe` | Preflight — Incident Management on + SLA fields present |
39
57
  | `GET /services/data/v67.0/query` | SOQL reads (BusinessHours, SlaProcess, EntityMilestone) via `query_params.q` |
58
+ | `GET /services/data/v67.0/connect/sla-management/sla-policies` | Phase 0.6 — detect the OOB "Standard Support for Incidents" policy via `query_params.processTypes=Incident` |
40
59
  | `POST /services/data/v67.0/connect/sla-management/milestone-types` | Create MilestoneType |
41
60
  | `POST /services/data/v67.0/connect/sla-management/sla-policies` | Create SLA Policy (SlaProcess) |
42
61
  | `POST /services/data/v67.0/connect/sla-management/sla-policies/<slaId>/milestones` | Attach Milestone |
43
62
  | `POST /services/data/v67.0/sobjects/Entitlement` | Create Entitlement (standard sObject) |
63
+ | `POST /services/data/v67.0/connect/sla-management/entitlement-criteria` | Phase 2-OOB — `describe` first, then attempt the OOB always-match criterion (`Subject NotEqual <sentinel>`); if the create still `400`s after using the described schema, fall back to a date-windowed Entitlement (the route works — a wrong-payload `400`, not a platform gap) |
44
64
  | `POST /services/data/v67.0/sobjects/Incident` | Create a test Incident |
65
+ | `POST /services/data/v67.0/sobjects/BusinessHours` | Phase 2.5 — create an IST (or other-timezone) BusinessHours for the policy/Entitlement (createable; **not** API-deletable) |
66
+ | `POST /services/data/v67.0/connect/sla-management/sla-policies/<slaId>/milestones/<milestoneId>/actions` | Phase 2.5 — attach a Warn/Escalate milestone action (delegate via the `create-milestone-action` op) |
45
67
 
46
68
  Minimum API version is **67.0** — `headless-360` currently only routes `v67.0+`.
47
69
 
@@ -55,13 +77,31 @@ guess returns `400 NOT_FOUND`; this exact string is the correct one. If it ever
55
77
  for a different org/release, the list-all route `GET /services/data/v67.0/connect/setup/discovery/features`
56
78
  returns every feature's apiName + status in one call.
57
79
 
58
- Enabling this feature flips `EntitlementSettings.IsEntitlementsEnabled` and **Simplified SLA
59
- Setup** together — Simplified SLA Setup has **no Tooling/Metadata API exposure**, so a Tooling
60
- PATCH to `EntitlementSettings` alone can never complete it.
80
+ **"SLA Management for IT Service" is a Setup Discovery composite of two sub-steps — Simplified SLA
81
+ Setup AND SLA Versioning — and reads as enabled/Complete only when BOTH are on.** In Setup it shows
82
+ **In Progress** while either is off.
83
+
84
+ **One enable call turns on both — they are inseparable.** The feature's enablement automation (the
85
+ platform recipe `turnOnSLAManagementForITService`) runs two hardcoded, non-optional steps: (1) turns
86
+ on Entitlements (`IsEntitlementsEnabled`) + Simplified SLA Setup + Pause Milestone; (2) turns on **SLA
87
+ Versioning** (`EntitlementSettings.IsEntitlementVersioningEnabled`, a one-way DB migration). So the
88
+ single feature `enable` call below **auto-enables SLA Versioning as a side effect** — no separate
89
+ versioning write is required, and there is **no supported way to enable Simplified SLA Setup while
90
+ leaving versioning off** (both steps are inseparable at the platform level). `IsEntitlementVersioningEnabled`
91
+ is a Tooling singleton (fixed Id `000000000000000AAA`, keyPrefix `0HE`, one row per org).
92
+
93
+ **SLA Versioning is permanent / one-way.** Salesforce rejects any attempt to turn it back off
94
+ ("Versioning cannot be disabled once it is enabled"), even if SLA Management is later disabled.
95
+
96
+ Because the enable is inseparable and versioning is irreversible, **never enable without explicit,
97
+ informed consent for the permanent switch** — an explicit permanence-gated `AskUserQuestion`, kept
98
+ separate from the master-enable ack (see *Ack structure* below). If the user declines, enable **nothing** (enabling the feature would flip versioning
99
+ anyway), SLA Management stays incomplete, and the run **halts**.
61
100
 
62
- **SLA Versioning is separate and NOT touched by the feature enable call.** It maps to
63
- `EntitlementSettings.IsEntitlementVersioningEnabled` (Tooling object, singleton, fixed Id
64
- `000000000000000AAA`, keyPrefix `0HE`, one row per org) and must be checked/enabled independently.
101
+ This is the root of W-23979084: the skill enabled the feature on a request that also said "don't
102
+ enable versioning," versioning turned on anyway (a side effect of the enable), and the skill then
103
+ **falsely reported it as off**. The fix: get permanence consent up front, and after the write re-read
104
+ and report the **real** state.
65
105
 
66
106
  ### Read — feature status
67
107
 
@@ -83,11 +123,11 @@ mcp__headless-360__dispatch_readonly({
83
123
  }
84
124
  ```
85
125
 
86
- - `status == "ENABLED"` → the feature (and Simplified SLA Setup) is on — move to the SLA Versioning
87
- read below.
126
+ - `status == "ENABLED"` → **Simplified SLA Setup** is on — now read SLA Versioning below. SLA
127
+ Management is fully enabled (the gate) only if **both** this is `ENABLED` **and** versioning is `true`.
88
128
  - `status == "NOT_ENABLED"` with non-empty `enableBlockedReasons` → **stop**, relay the reasons, do
89
129
  not attempt to enable.
90
- - `status == "NOT_ENABLED"` with empty `enableBlockedReasons` → confirm with the user, then enable.
130
+ - `status == "NOT_ENABLED"` with empty `enableBlockedReasons` → ack with the user (per *Ack structure*), then enable.
91
131
 
92
132
  ### Read — SLA Versioning
93
133
 
@@ -121,10 +161,17 @@ mcp__headless-360__dispatch({
121
161
  → 201 { "success": true }
122
162
  ```
123
163
 
124
- Do not trust `success: true` alone — re-run the status GET above and require `"status": "ENABLED"`
125
- before moving on.
164
+ **This single call enables the whole composite — Simplified SLA Setup *and*, as a side effect, the
165
+ permanent SLA Versioning.** Do not trust `success: true` alone — re-run the status GET above and
166
+ require `"status": "ENABLED"`, **and** re-run the SLA Versioning query and require
167
+ `IsEntitlementVersioningEnabled: true`, before moving on.
126
168
 
127
- ### Enable — SLA Versioning (only after explicit user confirmation, separately)
169
+ ### Enable — SLA Versioning (fallback only — normally unnecessary)
170
+
171
+ The feature enable above already turns versioning on, so you should **not** need a separate versioning
172
+ write. Use this Tooling PATCH **only** if the post-enable re-read shows versioning still `false` (e.g.
173
+ an older org whose enable automation predates the versioning step). It, too, requires explicit consent
174
+ for the permanent switch — versioning is irreversible either way.
128
175
 
129
176
  ```json
130
177
  mcp__headless-360__dispatch({
@@ -140,8 +187,45 @@ mcp__headless-360__dispatch({
140
187
 
141
188
  `FullName` is mandatory — the PATCH is rejected without it. The PATCH response body is empty on
142
189
  success — **re-run the Tooling query above and require `IsEntitlementVersioningEnabled: true`**
143
- before moving on, same rule as the SLA Policy create response later in this flow (never trust a
144
- write response alone).
190
+ before moving on (never trust a write response alone).
191
+
192
+ ### Ack structure — two separate consent questions
193
+
194
+ Enabling the feature is **one inseparable action with a permanent consequence**: it turns on the SLA
195
+ Management feature **and, as a one-way side effect, permanently enables SLA Versioning**. **Only SLA
196
+ Versioning is permanent.** Scope the reversibility precisely so the customer is neither over- nor
197
+ under-warned:
198
+
199
+ - **Master Incident Management pref** — fully reversible; enabling it has no permanent side effect.
200
+ - **SLA Management for IT Service feature** — the feature toggle can be turned off again later, **but
201
+ turning it off does NOT turn SLA Versioning back off**. Versioning stays on permanently once the
202
+ enable flips it. So do **not** describe the feature as cleanly "reversible" without this caveat — a
203
+ customer could otherwise assume disabling SLA Management undoes versioning, which is false.
204
+ - **SLA Versioning** — permanent / one-way; guarded against disable at the platform level.
205
+
206
+ **Ask two separate `AskUserQuestion`s — never merge them into one.** The master enable and the
207
+ permanent-versioning consent carry very different stakes (reversible prerequisite vs. irreversible
208
+ consequence); bundling them forces an all-or-nothing accept and conflates the two. Do **not** offer a
209
+ "versioning-off" path (none exists). Build each from the reads, not a fixed script.
210
+
211
+ - If **both** the feature and versioning are already on → skip the acks; the gate passes.
212
+ - **Q1 — master prerequisite (only if master Incident Mgmt is `NOT_ENABLED`):** ask to enable it
213
+ first. It's **reversible** — present it as a prerequisite with **no** permanence warning. Offer
214
+ **Enable** or **Stop — make no changes**. A declined master → HALT.
215
+ - **Q2 — permanence ack for the feature (a distinct question, after the master is on):** if the
216
+ feature is off (and `enableBlockedReasons` is empty) → ask, in customer terms: enabling **SLA
217
+ Management for IT Service** also turns on **SLA Versioning**, which **can't be turned off once
218
+ enabled** — the SLA Management feature itself can be turned off again later, but that will **not**
219
+ turn Versioning back off; Versioning is permanent. Offer **Enable** or **Stop — make no changes**.
220
+ - **Any decline — including a request to enable Simplified SLA Setup but *not* versioning — means
221
+ HALT.** There is no way to honor "Simplified without versioning" (enabling the feature flips
222
+ versioning anyway); enable **nothing** and do not proceed to SLA/milestone setup. Say plainly why —
223
+ they're inseparable and versioning is permanent.
224
+ - **Never** enable silently or bury the permanent switch in a default — a bare or repeated "enable
225
+ SLA" is not consent for the permanent SLA Versioning switch. This is the W-23979084 bug.
226
+ - **After enabling, re-read both** and report the real, both-on state — never trust the write
227
+ response. The gate passes only when Simplified SLA Setup is `ENABLED` **and**
228
+ `IsEntitlementVersioningEnabled` is `true`.
145
229
 
146
230
  ---
147
231
 
@@ -189,14 +273,28 @@ mcp__headless-360__dispatch_readonly({
189
273
 
190
274
  The endpoint returns the full feature catalog (~763 entries, ~1.1 MB) and does not honor
191
275
  `?apiName=` server-side. Filter `body.features[]` client-side to the element where
192
- `apiName == "service-cloud-itsm-incident"` and read its `status` (`ENABLED` / `NOT_ENABLED`).
193
-
194
- **Auto-delegate rule**: if `status != "ENABLED"`, delegate to
195
- `service-itsm-incident-mgmt-configure` inline before continuing — that skill runs its own
196
- confirm-to-write against the enable route (`POST .../setup/discovery/feature/service-cloud-itsm-incident/enable`)
197
- and returns after the flip. Re-read this step to verify `status == "ENABLED"` before
198
- continuing. If the user declines the delegation, halt — every downstream SLA artifact
199
- depends on the master being on.
276
+ `apiName == "service-cloud-itsm-incident"` — the **exact** apiName. Read its `status`
277
+ (`ENABLED` / `NOT_ENABLED` / `NOT_AVAILABLE`).
278
+
279
+ > **Never substitute a look-alike.** The catalog also contains `service-cloud-incident-management`
280
+ > — that is **generic Service Cloud Incident Management** (built on Case Management, so its
281
+ > `dependencyStatuses` chain through `service-cloud-case-management` → Support Settings Default Case
282
+ > Owner + Automated Case User). It is **not** the ITSM master this skill targets, and enabling it
283
+ > (plus its Case chain) does **not** unlock ITSM Incident SLA. If `service-cloud-itsm-incident` is
284
+ > absent or `NOT_AVAILABLE`, do **not** fall back to it — halt (see below).
285
+
286
+ **Status → action** (never auto-enable the master as an implied SLA dependency):
287
+
288
+ - `ENABLED` → proceed.
289
+ - `NOT_AVAILABLE` (ITSM Incident Management license/entitlement not present on the org) → **halt and
290
+ surface it** — the master cannot be enabled here, so there is no ack and no delegate. This is the
291
+ correct terminal outcome on an unlicensed org (do not pursue Case Management / generic Incident
292
+ Management as a workaround).
293
+ - `NOT_ENABLED` → get an explicit `AskUserQuestion` ack first (per SKILL.md Phase 1 step 1), then
294
+ delegate to `service-itsm-incident-mgmt-configure` inline — that skill runs its own confirm-to-write
295
+ against `POST .../setup/discovery/feature/service-cloud-itsm-incident/enable` and returns after the
296
+ flip. Re-read this step to verify `status == "ENABLED"` before continuing. If the user declines,
297
+ halt — every downstream SLA artifact depends on the master being on.
200
298
 
201
299
  ## Preflight B — SLA fields on the Incident sObject
202
300
 
@@ -278,7 +376,7 @@ verify state via SOQL:
278
376
  mcp__headless-360__dispatch_readonly({
279
377
  "url": "/services/data/v67.0/query",
280
378
  "method": "GET",
281
- "query_params": { "q": "SELECT Id, Name, SObjectType, IsActive, BusinessHoursId FROM SlaProcess WHERE Id = '<slaId>'" }
379
+ "query_params": { "q": "SELECT Id, Name, SobjectType, IsActive, BusinessHoursId FROM SlaProcess WHERE Id = '<slaId>'" }
282
380
  })
283
381
  ```
284
382
 
@@ -302,7 +400,7 @@ mcp__headless-360__dispatch({
302
400
  "milestoneCriteria": [
303
401
  {
304
402
  "milestoneState": "Active",
305
- "milestoneAgreementType": "Warning",
403
+ "milestoneAgreementType": "SLA",
306
404
  "filterType": "RuleFilter",
307
405
  "filterItems": [
308
406
  { "table": "Incident", "column": "Status", "operator": "NotEqual", "order": 1, "value": "Closed" }
@@ -313,7 +411,136 @@ mcp__headless-360__dispatch({
313
411
  })
314
412
  ```
315
413
 
316
- `milestoneCriteria` is mandatory. Success: `body.id` is the new Milestone Id.
414
+ `milestoneCriteria` is mandatory. `milestoneAgreementType` is mandatory per the UI and lives **inside each `milestoneCriteria[]` item** (it maps to the `MilestoneCriteria.MilestoneAgreementType` sub-entity field — sending it at the top level of the milestone body returns `JSON_PARSER_ERROR: Unrecognized field`). Valid UI values are **`SLA`** (customer-facing agreement) or **`OLA`** (internal / operational). The API accepts any string because the underlying field is plain `Text(40)` with no server-side picklist enforcement — an unrecognized value persists to the DB but the UI treats it as blank; omitting the field entirely also succeeds silently but leaves the record's Milestone Agreement Type null (W-23959162). Success: `body.id` is the new Milestone Id.
415
+
416
+ ---
417
+
418
+ ## Milestone Actions (Phase 2.5 — Warn / Escalate)
419
+
420
+ A **milestone action** fires automation at a checkpoint of an existing milestone — a **Warning**
421
+ (before target), a **Violation** (at/after target), or a **Success** (on completion). This is how the
422
+ skill implements "warn at 75%, escalate on breach". It runs **only** when the user asked to
423
+ warn/escalate/notify, **after** the milestones exist (Phase 2 or Phase 2-OOB).
424
+
425
+ **Scope — apply to every milestone the user named for that policy.** "Warn at 75%, escalate on breach"
426
+ attaches to **each** milestone the request scopes it to (e.g. a `15-min response` *and* a `2-hour
427
+ resolution` → warn+escalate on **both**), not just one. Each checkpoint on each milestone is a
428
+ **separate** `create-milestone-action` call (one action sub-object per call), and the "warn at X%"
429
+ offset is computed from **that milestone's own** target (75% of 15 min ≠ 75% of 120 min). Confirm the
430
+ whole set in a single `AskUserQuestion` before any write, then dispatch per (milestone × checkpoint).
431
+
432
+ ### Delegate to `create-milestone-action` — don't hardcode the body
433
+
434
+ The full request schema is owned by the approved headless **`create-milestone-action`** operation.
435
+ **Resolve it live** rather than reconstructing the polymorphic body from memory:
436
+
437
+ ```text
438
+ mcp__headless-360__discover(query="add milestone action warning violation escalation")
439
+ mcp__headless-360__describe(id="<create-milestone-action operation id>")
440
+ ```
441
+
442
+ Then `dispatch` the `POST` it returns:
443
+ `/services/data/v67.0/connect/sla-management/sla-policies/<slaId>/milestones/<milestoneId>/actions`.
444
+
445
+ ### Checkpoint roles (the `checkpoint` block)
446
+
447
+ Send **exactly one** action sub-object, plus the checkpoint role. `timeLength`/`timeUnit` go **inside**
448
+ `checkpoint` (top-level → `JSON_PARSER_ERROR`). `timeUnit` ∈ **`Minutes` | `Hours` | `Days`** only.
449
+ **Never** send `isInitiationCheckpoint` (hard `400`).
450
+
451
+ | Role | Flags | Timing |
452
+ |------|-------|--------|
453
+ | Success | `isSuccessCheckpoint: true`, `checkpoint.isWarning: false` | none |
454
+ | Warning | `isSuccessCheckpoint: false`, `checkpoint.isWarning: true` | `timeLength`+`timeUnit` **before** target |
455
+ | Violation | `isSuccessCheckpoint: false`, `checkpoint.isWarning: false` | `timeLength`+`timeUnit` **after** target (`timeLength: 0` = at breach) |
456
+
457
+ ### "Warn at X%" → offset before target
458
+
459
+ A warning fires an *offset before* the target, so convert the percentage:
460
+
461
+ ```text
462
+ offsetBeforeTarget = round( milestoneTargetMinutes × (1 − X/100) )
463
+ ```
464
+
465
+ - 2-hour (120-min) resolution, warn at 75% → `120 × 0.25 = 30` min before.
466
+ - 8-hour (480-min) milestone, warn at 75% → `120` min before.
467
+ - Round to whole minutes; a 15-min milestone at 75% → `3.75 → 4` min before (very tight, but honor it
468
+ if the user asked to warn on a short milestone; if they left the target open, the longer resolution
469
+ milestone gives a more useful warning window).
470
+
471
+ "Escalate **on breach**" → a Violation with `timeLength: 0`.
472
+
473
+ ### Proven bodies (live-validated, Field Update)
474
+
475
+ **Default action is a Field Update** — self-contained, no org dependencies. `actionFlow` returns an
476
+ opaque `201 / success:false / INTERNAL_SERVER_ERROR` on empty-flow auto-create in some orgs — avoid it
477
+ as the default; Email Alert needs a pre-built template. Warning (warn at 75% of a 2-hr milestone → 30
478
+ min before):
479
+
480
+ ```json
481
+ mcp__headless-360__dispatch({
482
+ "url": "/services/data/v67.0/connect/sla-management/sla-policies/<slaId>/milestones/<milestoneId>/actions",
483
+ "method": "POST",
484
+ "body": {
485
+ "isSuccessCheckpoint": false,
486
+ "checkpoint": { "isWarning": true, "timeLength": 30, "timeUnit": "Minutes" },
487
+ "entityName": "Incident",
488
+ "actionFieldUpdate": {
489
+ "name": "SLA Warn 75pct RES", "sourceTable": "Incident", "targetTable": "Incident",
490
+ "columnEnumOrId": "Priority", "developerName": "SLA_Warn_75_RES",
491
+ "operationString": "LITERAL", "literal": "High"
492
+ }
493
+ }
494
+ })
495
+ ```
496
+
497
+ Violation (escalate on breach → `Priority = Critical`): same shape with
498
+ `checkpoint: { "isWarning": false, "timeLength": 0, "timeUnit": "Minutes" }`, `name`
499
+ `"SLA Escalate on Breach RES"`, `developerName` `SLA_Escalate_Breach_RES`, `literal` `"Critical"`.
500
+
501
+ **Make `name`/`developerName` unique per milestone.** A `WorkflowFieldUpdate` `DeveloperName` is unique
502
+ on the Incident object, so reusing `SLA_Warn_75` on a second milestone fails with
503
+ `DUPLICATE_DEVELOPER_NAME`. Suffix both with the milestone (the `_RES` above for Resolution, `_FR`
504
+ for First Response — a 15-min First Response at 75% warns 4 min before, `timeLength: 4`). For a custom-field target use its `CustomField` id (`00N…`), not the `__c` API name.
505
+
506
+ ### Confirm from the response body — no read-back of the attachment
507
+
508
+ The endpoint returns **`201` even on failure**. Real success = `body.success == true` **and** a
509
+ non-empty `body.actionMappings`. A **timed** checkpoint — one with an offset > 0, i.e. a Warning fired
510
+ some minutes *before* target — **also** returns a `triggerId`. A breach Violation with `timeLength: 0`
511
+ fires *at* target and may return **no** `triggerId`; do **not** treat its absence as failure — for it,
512
+ `success` + non-empty `actionMappings` is the whole signal. A bad body shape returns an opaque
513
+ `201 / success:false / INTERNAL_SERVER_ERROR`.
514
+
515
+ **Read-back is partial.** There is **no read-back of the checkpoint *attachment*** — nothing headless
516
+ echoes which checkpoint (Warning/Violation) or offset an action is wired to. (The Connect
517
+ `GET .../milestones/<id>/actions?entityName=Incident` returns the *builder* catalog — available
518
+ actions + field metadata, with `previouslyAttachedActions: []` — **not** the configured state; and
519
+ `MilestoneAction` is not a SOQL sObject.) The action **definitions** themselves *are* Tooling-queryable
520
+ if you only need to confirm the objects persisted — e.g. `SELECT Id, Name FROM WorkflowFieldUpdate
521
+ WHERE Id IN (<the actionMapping ids from the create responses>)` for the default Field Update action
522
+ (other action types map to `WorkflowAlert` / `Task` / etc.) — but that confirms **existence only**, not
523
+ the attachment or offset, so it is an optional debugging aid, not the verification. There is also **no
524
+ clean headless delete**. Because the attachment can't be read back, the full action set **must be
525
+ confirmed before writing**. Up-front authorization (the Phase 1.4 skip condition (c)) waives the
526
+ interactive `AskUserQuestion` re-ask exactly as Phase 1.5 does, but the set must still be **narrated**
527
+ before the writes; verification is body-based, not a GET.
528
+
529
+ ### "IST business hours" is a policy-level BusinessHours, not an action field
530
+
531
+ Milestone actions carry **no** timezone/business-hours attribute. "IST business hours" is a
532
+ `BusinessHours` record (`TimeZoneSidKey: "Asia/Kolkata"` + weekly windows) attached at the **policy /
533
+ Entitlement** level (`Entitlement.BusinessHoursId`). Resolve-then-create:
534
+
535
+ 1. Look up an existing BusinessHours with `TimeZoneSidKey = 'Asia/Kolkata'`; **reuse** if found.
536
+ 2. Else create one — `POST /sobjects/BusinessHours` (`Name`, `TimeZoneSidKey: "Asia/Kolkata"`,
537
+ default Mon–Fri 09:00–18:00 windows). `BusinessHours` is **createable but not API-deletable**, so
538
+ confirm before creating; never mutate the org `Default` record and never set `IsDefault`.
539
+ 3. Attach via the policy/Entitlement `BusinessHoursId`.
540
+
541
+ **Caveat — read it live and disclose:** if the org has `ignoreMilestoneBusinessHours = true`, milestone
542
+ SLA timers run **24/7** and ignore business hours, so an IST BusinessHours is recorded but does **not**
543
+ shift the milestone clock. State this plainly instead of implying IST changed the timers.
317
544
 
318
545
  ---
319
546
 
@@ -343,6 +570,99 @@ Success: `body.id`.
343
570
 
344
571
  ---
345
572
 
573
+ ## Predefined Incident Policy (Phase 0.6 detect + Phase 2-OOB seed)
574
+
575
+ The out-of-box **"Standard Support for Incidents"** policy is what Salesforce seeds from Setup's
576
+ "Create Predefined Policies" step (Incident process type only). That step is Aura-only and not
577
+ headless-reachable, but it seeds via the **same backend** as the public `/connect/sla-management/*`
578
+ routes above — so the skill replicates it exactly with routes it already uses. The full template
579
+ (policy flags, 2 milestone types, 8 priority-tiered milestones, entitlement criterion) lives in
580
+ **`assets/predefined-incident-policy.json`** — load and follow it; the values below are the shape.
581
+
582
+ ### Detect first (no server idempotency → mandatory)
583
+
584
+ Re-seeding is **not** idempotent — a second seed duplicates every artifact. Before offering to seed,
585
+ read the existing Incident policies and name-match:
586
+
587
+ ```json
588
+ mcp__headless-360__dispatch_readonly({
589
+ "url": "/services/data/v67.0/connect/sla-management/sla-policies",
590
+ "method": "GET",
591
+ "query_params": { "processTypes": "Incident" }
592
+ })
593
+ ```
594
+
595
+ If any returned policy's name is **"Standard Support for Incidents"**, it is already seeded — report
596
+ it and do **not** re-seed. (Fallback: SOQL `SELECT Id, Name FROM SlaProcess WHERE SobjectType =
597
+ 'Incident' AND Name = 'Standard Support for Incidents'`.)
598
+
599
+ ### Seed recipe (only if not already present)
600
+
601
+ Uses the Phase 2 routes above, in this order:
602
+
603
+ 1. **Resolve the 2 MilestoneTypes — detect first, create only what is missing.** Enabling the SLA
604
+ Management feature pre-seeds a default MilestoneType catalog (commonly `First Response`,
605
+ `Follow Up`, `Periodic Update`, **`Resolve Within`**), so a blind `POST .../milestone-types` for a
606
+ name that already exists returns **HTTP 500 ("already exists")** and leaves the policy half-seeded.
607
+ First read the catalog — SOQL `SELECT Id, Name FROM MilestoneType WHERE Name IN ('Acknowledge
608
+ Within', 'Resolve Within')` (or `GET .../milestone-types`) — **reuse any match by id**, and `POST
609
+ .../milestone-types` (`recurrenceType: OneTime`) **only** for the name(s) not already present.
610
+ Capture both ids (whether reused or created).
611
+ 2. Create the SLA Policy `Standard Support for Incidents` (`POST .../sla-policies`) with
612
+ `processType: "Incident"`, `businessHourId` = default, `createdDateEntryCriteria: true`,
613
+ `closedExitCriteria: true`, `versionDefault: true`, **`active: true`** (create it active directly —
614
+ do **not** use the Connect activate PATCH, which can 500 headless). Verify via SOQL on `SlaProcess`.
615
+ 3. Attach the **8 priority-tiered milestones** (`POST .../sla-policies/<id>/milestones`, one per row).
616
+ Reuse `assets/attach-milestone.json`. Validate each Priority/Status value against the live
617
+ `Incident` picklist first. For the **mid tier**, map to the org's actual mid-priority label —
618
+ `Moderate` on the standard ITSM picklist, but many orgs label it `Medium` — and seed orders 5–6
619
+ with whichever the live picklist carries rather than dropping the tier. Drop a row **only** when its
620
+ value is genuinely absent from the picklist, and note any dropped or relabeled tier in the report.
621
+
622
+ | order | milestoneType | timeTrigger | active criterion (Priority) | completion (Status) |
623
+ |-------|---------------|-------------|-----------------------------|---------------------|
624
+ | 1 | Acknowledge Within | 30 | `Equals Critical` | `NotEqual New` |
625
+ | 2 | Resolve Within | 120 | `Equals Critical` | `In [Resolved, Completed, Closed]` |
626
+ | 3 | Acknowledge Within | 60 | `Equals High` | `NotEqual New` |
627
+ | 4 | Resolve Within | 240 | `Equals High` | `In [Resolved, Completed, Closed]` |
628
+ | 5 | Acknowledge Within | 240 | `Equals Moderate` | `NotEqual New` |
629
+ | 6 | Resolve Within | 960 | `Equals Moderate` | `In [Resolved, Completed, Closed]` |
630
+ | 7 | Acknowledge Within | 240 | `Equals Low` | `NotEqual New` |
631
+ | 8 | Resolve Within | 960 | `Equals Low` | `In [Resolved, Completed, Closed]` |
632
+
633
+ The **active** criterion (`Priority Equals <tier>`) is the one the public Attach-Milestone
634
+ `milestoneCriteria` carries (`milestoneState: Active`, `milestoneAgreementType: SLA`,
635
+ `filterType: RuleFilter`) — seeding it engages each milestone. The OOB also carries completion
636
+ (`Status In …`) and cancel (`Priority NotEqual <tier>`) criteria (`milestoneState` Complete / Cancel);
637
+ confirm the route accepts those states in the smoke test — if not, the active criterion alone is
638
+ sufficient for engagement (matches `examples/milestone-patterns.md` Pattern 3).
639
+
640
+ **OR / In have no single-row form.** `filterItems` AND by default and there is no `In` operator. The
641
+ Priority tiers are already pre-split above (each row is a single `Priority Equals <tier>`, Moderate and
642
+ Low as separate rows 5–8), so no OR is needed for Priority. For the `Status In` completion sets, either
643
+ use `filterLogic: "1 OR 2"` if the route accepts it (verify live) or split into one row per value —
644
+ behavior-equivalent.
645
+
646
+ 4. Create the Entitlement (`POST /sobjects/Entitlement`) on the resolved Account, `SlaProcessId` =
647
+ the seeded policy, backdated `StartDate`. **Attempt** the OOB always-match entitlement criterion
648
+ (`Subject NotEqual <sentinel>`, see the asset) via `POST /connect/sla-management/entitlement-criteria`
649
+ so the policy auto-matches every Incident like true OOB. **First `describe` that operation and send
650
+ its exact input fields** — do **not** reuse the milestone-criteria body shape: `entitlement-criteria`
651
+ rejects `filterType` (`400 JSON_PARSER_ERROR: Unrecognized field "filterType"`); its criterion body
652
+ differs. If the create still fails after using the described schema, fall back to the date-windowed
653
+ Entitlement alone and **disclose only the consequence, in plain customer terms**: the seeded policy
654
+ then engages on Incidents wired to this Entitlement (`EntitlementId` set), not on every Incident
655
+ automatically — to make it apply to all Incidents, add the always-match criterion via **Setup →
656
+ Entitlement Management**. **Do NOT tell the user the route is "unreachable" or its schema
657
+ "undiscoverable"** — that is inaccurate; the route works, the criterion body just needs its correct
658
+ fields (a wrong-payload `400`, not a platform gap), and misattributing it reads as a bug. Never
659
+ surface the raw sentinel string or a `JSON_PARSER_ERROR` in the customer report. The date-windowed
660
+ Entitlement plus the milestone criteria are still enough to engage the Phase 3 test Incident.
661
+ 5. Verify per **Verify SLA engagement** below with a **Critical** test Incident (a Critical Priority
662
+ matches orders 1–2, so an `EntityMilestone` spawns), then **STOP** — do not offer custom.
663
+
664
+ ---
665
+
346
666
  ## Verify SLA engagement
347
667
 
348
668
  Create a test Incident:
@@ -386,9 +706,9 @@ mcp__headless-360__dispatch_readonly({
386
706
  | Response wrapper | Connect/`/sobjects`/`/query` are singly wrapped — read `body`. Aura `/headless/invoke/…` routes (not used here) are doubly wrapped. |
387
707
  | Corpus vs. registry drift | `discover` may not rank the SLA POST routes at the top — the routes are still known-good; `describe` + `dispatch` on the canonical path works either way. |
388
708
  | SLA Policy create response is null | `POST /sla-policies` echoes most fields as `null` — always verify via SOQL on `SlaProcess`. |
389
- | Milestone criteria mandatory | Omitting `milestoneCriteria` returns `400: Criteria details cannot be empty`. |
390
- | Formula filter → 500 | `filterType: "Formula"` triggers an internal server error. Use `filterType: "RuleFilter"` with concrete `filterItems[]`. |
391
- | Filter operator enum | Use `Equals` (not `Equal`), `NotEqual` (not `NotEquals`/`NotEqualTo`/`!=`). Wrong shape → `POST_BODY_PARSE_ERROR: Invalid value for Filter Operation Enum`. |
709
+ | Milestone filter payload | `milestoneCriteria` is mandatory (omitting it → `400: Criteria details cannot be empty`). Use `filterType: "RuleFilter"` with concrete `filterItems[]` — `filterType: "Formula"` triggers a 500. Operators are `Equals` (not `Equal`) and `NotEqual` (not `NotEquals`/`NotEqualTo`/`!=`); wrong forms → `POST_BODY_PARSE_ERROR: Invalid value for Filter Operation Enum`. |
392
710
  | `slaProcessId` rejected in body | The server returns `JSON_PARSER_ERROR: Unrecognized field "slaProcessId"` — the id is in the path only. |
393
- | Entitlement status date-computed | Future `StartDate` → `Inactive`. Backdate `StartDate` to yesterday for immediate SLA engagement in testing. |
394
- | Entitlement is standard sObject | Create via `POST /sobjects/Entitlement`, not the Connect surface. |
711
+ | Entitlement create + status | Create via `POST /sobjects/Entitlement` (standard sObject, not the Connect surface). Status is date-computed: a future `StartDate` → `Inactive`; backdate `StartDate` to yesterday for immediate SLA engagement in testing. |
712
+ | OOB seed has no idempotency | `POST .../sla-policies` does not dedupe — re-seeding "Standard Support for Incidents" duplicates every artifact. Detect first via `GET .../sla-policies?processTypes=Incident` and name-match before seeding. |
713
+ | Connect activate PATCH may 500 | The OOB backend flips the policy active via a Connect activate call; headless, that PATCH can 500. Create the SlaProcess with `active: true` directly instead (as the custom flow does). |
714
+ | Never leak a record Id | In **every** user-facing message (interim narration *and* the final report, incl. "created milestone …" progress lines), refer to the Phase-3 test Incident by its **`IncidentNumber`** (the verify SOQL selects it) and milestones by their **`MilestoneType.Name`** — never the 15/18-char record Id. |