@salesforce/afv-skills 1.61.0 → 1.63.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 (44) hide show
  1. package/package.json +3 -3
  2. package/skills/agentforce-architecture-analyze/README.md +2 -1
  3. package/skills/agentforce-d360-analyze/README.md +1 -1
  4. package/skills/agentforce-generate/README.md +1 -0
  5. package/skills/crm-analytics-wave-generate/SKILL.md +212 -0
  6. package/skills/crm-analytics-wave-generate/assets/dashboard-template.json +66 -0
  7. package/skills/crm-analytics-wave-generate/assets/wapp-meta-template.xml +10 -0
  8. package/skills/crm-analytics-wave-generate/assets/wdash-meta-template.xml +6 -0
  9. package/skills/crm-analytics-wave-generate/assets/wdpr-meta-template.xml +11 -0
  10. package/skills/crm-analytics-wave-generate/examples/industry-binding-dashboard.wdash +67 -0
  11. package/skills/crm-analytics-wave-generate/examples/opportunity-revenue-recipe.wdpr +132 -0
  12. package/skills/crm-analytics-wave-generate/examples/pipeline-by-industry-quarter.wdpr +236 -0
  13. package/skills/crm-analytics-wave-generate/examples/wdpr-skeleton.wdpr +62 -0
  14. package/skills/crm-analytics-wave-generate/references/dashboard-authoring.md +157 -0
  15. package/skills/crm-analytics-wave-generate/references/dataset-hygiene.md +27 -0
  16. package/skills/crm-analytics-wave-generate/references/external-data-upload.md +61 -0
  17. package/skills/crm-analytics-wave-generate/references/method-decision-tree.md +12 -0
  18. package/skills/crm-analytics-wave-generate/references/r3-node-schema.md +194 -0
  19. package/skills/crm-analytics-wave-generate/references/scripts-reference.md +17 -0
  20. package/skills/crm-analytics-wave-generate/references/ui-section-template.md +68 -0
  21. package/skills/crm-analytics-wave-generate/scripts/check_connector_error.sh +53 -0
  22. package/skills/crm-analytics-wave-generate/scripts/create_app.js +59 -0
  23. package/skills/crm-analytics-wave-generate/scripts/deploy_and_run_recipe.js +122 -0
  24. package/skills/crm-analytics-wave-generate/scripts/fetch_dataset_xmd.js +59 -0
  25. package/skills/crm-analytics-wave-generate/scripts/find_unused_dataset_fields.js +96 -0
  26. package/skills/crm-analytics-wave-generate/scripts/gen_synthetic_dataset.js +137 -0
  27. package/skills/crm-analytics-wave-generate/scripts/patch_t_oppo_view.js +99 -0
  28. package/skills/crm-analytics-wave-generate/scripts/probe_recipe.js +47 -0
  29. package/skills/crm-analytics-wave-generate/scripts/upload_dataset.js +119 -0
  30. package/skills/crm-analytics-wave-generate/scripts/verify_dashboard_steps.js +99 -0
  31. package/skills/crm-analytics-wave-generate/scripts/verify_synthetic_dataset.js +86 -0
  32. package/skills/service-itsm-agentic-setup-incident-management/SKILL.md +60 -20
  33. package/skills/service-itsm-agentic-setup-incident-management/examples/output-templates.md +5 -1
  34. package/skills/service-itsm-agentic-setup-incident-management/references/incident-persona-psg.md +2 -2
  35. package/skills/service-itsm-agentic-setup-incident-management/references/incident-preferences.md +2 -2
  36. package/skills/service-itsm-agentic-setup-incident-management/references/major-incident-management.md +5 -5
  37. package/skills/service-itsm-agentic-setup-incident-management/references/service-mgmt-privilege.md +5 -5
  38. package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +67 -100
  39. package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/attach-milestone-action.json +2 -2
  40. package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/attach-milestone.json +2 -2
  41. package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/milestone-patterns.md +23 -22
  42. package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/output-templates.md +3 -3
  43. package/skills/service-itsm-agentic-setup-incident-sla-configure/references/mcp-invocation.md +182 -58
  44. package/skills/service-itsm-agentic-setup-incident-sla-configure/references/workflow.md +157 -88
@@ -17,16 +17,18 @@ skill never handles credentials or an org alias — everything is derived from t
17
17
 
18
18
  - [Response envelope](#response-envelope)
19
19
  - [Routes](#routes)
20
- - [Phase 0.5 — SLA Management for IT Service prerequisite gate](#phase-05--sla-management-for-it-service-prerequisite-gate)
20
+ - [Phase 1a — IT Service Management enablement gate](#phase-1a--it-service-management-enablement-gate)
21
+ - [Phase 1b — SLA Management for IT Service prerequisite gate](#phase-1b--sla-management-for-it-service-prerequisite-gate)
21
22
  - [Discovery — always run first](#discovery--always-run-first)
22
23
  - [Preflight A — Master Incident Management pref (direct read)](#preflight-a--master-incident-management-pref-direct-read)
23
24
  - [Preflight B — SLA fields on the Incident sObject](#preflight-b--sla-fields-on-the-incident-sobject)
24
- - [Default BusinessHours](#default-businesshours)
25
+ - [Resolve Business Hours](#resolve-business-hours)
25
26
  - [Create MilestoneType](#create-milestonetype)
26
27
  - [Create SLA Policy (SlaProcess)](#create-sla-policy-slaprocess)
27
28
  - [Attach Milestone](#attach-milestone)
28
- - [Milestone Actions (Phase 2.5 — Warn / Escalate)](#milestone-actions-phase-25--warn--escalate)
29
- - [Predefined Incident Policy (Phase 0.6 detect + Phase 2-OOB seed)](#predefined-incident-policy-phase-06-detect--phase-2-oob-seed)
29
+ - [Milestone Actions (Phase 5 — Warn / Escalate)](#milestone-actions-phase-5--warn--escalate)
30
+ - [Predefined Incident Policy (Phase 2 detect + Phase 4B seed)](#predefined-incident-policy-phase-2-detect--phase-4b-seed)
31
+ - [Priority matrix flag (Phase 2 note + Phase 6 stopping rule)](#priority-matrix-flag-phase-2-note--phase-6-stopping-rule)
30
32
  - [Verify SLA engagement](#verify-sla-engagement)
31
33
  - [Gotchas](#gotchas)
32
34
 
@@ -39,8 +41,9 @@ singly wrapped:
39
41
  { "status_code": 200, "body": <REST/Connect response> }
40
42
  ```
41
43
 
42
- Read `body`. (Only `/headless/invoke/…` Aura-controller routes are doubly wrapped as `body.body`;
43
- this skill uses none.)
44
+ Read `body`. The `/headless/invoke/platform/slasettings/…` routes (Phases 1b, 2 and 4B) return the
45
+ same shape: the invoke envelope is unwrapped before the response reaches you, so read `body` for
46
+ them too.
44
47
 
45
48
  ---
46
49
 
@@ -48,14 +51,15 @@ this skill uses none.)
48
51
 
49
52
  | Method + path | Purpose |
50
53
  |---------------|---------|
51
- | `GET /headless/invoke/platform/slasettings/get-sla-management-permission` | Phase 0.5 — read whether SLA Management is on (composite: Entitlements + Simplified SLA Setup + Pause Milestone). Delegated to `itsm-shakti/SLASettings` |
52
- | `PATCH /headless/invoke/platform/slasettings/set-sla-management-permission` | Phase 0.5 — turn SLA Management on (`isEnabled:true`; flips the three prefs atomically; requires Entitlements already on or it throws). **Reversible.** Delegated to `itsm-shakti/SLASettings` |
53
- | `GET /headless/invoke/platform/slasettings/get-sla-versioning-permission` | Phase 0.5 — read whether SLA Versioning is on. Delegated to `itsm-shakti/SLASettings` |
54
- | `PATCH /headless/invoke/platform/slasettings/set-sla-versioning-permission` | Phase 0.5 — turn SLA Versioning on (`isEnabled:true`). **Separate write; permanent / one-way** — the controller refuses to disable it. Delegated to `itsm-shakti/SLASettings` |
54
+ | `GET /headless/invoke/platform/slasettings/get-sla-management-permission` | Phase 1b — read whether SLA Management is on (composite: Entitlements + Simplified SLA Setup + Pause Milestone). Delegated to `itsm-shakti/SLASettings` |
55
+ | `PATCH /headless/invoke/platform/slasettings/set-sla-management-permission` | Phase 1b — turn SLA Management on (`isEnabled:true`; flips the three prefs atomically; requires Entitlements already on or it throws). **Reversible.** Delegated to `itsm-shakti/SLASettings` |
56
+ | `GET /headless/invoke/platform/slasettings/get-sla-versioning-permission` | Phase 1b — read whether SLA Versioning is on. Delegated to `itsm-shakti/SLASettings` |
57
+ | `PATCH /headless/invoke/platform/slasettings/set-sla-versioning-permission` | Phase 1b — turn SLA Versioning on (`isEnabled:true`). **Separate write; permanent / one-way** — the controller refuses to disable it. Delegated to `itsm-shakti/SLASettings` |
58
+ | `GET /services/data/v{version}/setup/org/preferences/IncPriorityMatrixEnabled` | Phase 2 / 6 — is the Impact × Urgency priority matrix on? Read-only warning, not a gate |
55
59
  | `GET /services/data/v{version}/sobjects/Incident/describe` | Preflight — Incident Management on + SLA fields present |
56
60
  | `GET /services/data/v{version}/query` | SOQL reads (BusinessHours, SlaProcess, EntityMilestone) via `query_params.q` |
57
- | `GET /headless/invoke/platform/slasettings` | Phase 0.6 / 2-OOB — the seeder's existence map (get-existing-checkbox-states); lowercase keys `{incident,problem,changeRequest}`, `true` = default already seeded (dedup read) |
58
- | `PATCH /headless/invoke/platform/slasettings/save-selected-options` | Phase 2-OOB — seed the predefined bundle in one call; body `{"selectedOptions":["incident"]}` (**lowercase** — capitalized 500s); provisions the full active policy + Entitlement + criteria |
61
+ | `GET /headless/invoke/platform/slasettings` | Phase 2 / 4B — the seeder's existence map (get-existing-checkbox-states); lowercase keys `{incident,problem,changeRequest}`, `true` = default already seeded (dedup read) |
62
+ | `PATCH /headless/invoke/platform/slasettings/save-selected-options` | Phase 4B — seed the predefined bundle in one call; body `{"selectedOptions":["incident"]}` (**lowercase** — capitalized 500s); provisions the full active policy + Entitlement + criteria |
59
63
  | `GET /services/data/v{version}/connect/sla-management/sla-policies` | List Incident SLA policies via `query_params.processTypes=Incident` (coexistence detect — is another active Incident policy present?) |
60
64
  | `POST /services/data/v{version}/connect/sla-management/milestone-types` | Create MilestoneType |
61
65
  | `POST /services/data/v{version}/connect/sla-management/sla-policies` | Create SLA Policy (SlaProcess) |
@@ -63,8 +67,8 @@ this skill uses none.)
63
67
  | `PATCH /services/data/v{version}/connect/sla-management/sla-policies/<slaId>/status?isActive=true&createEntitlement=true` | **Custom flow** — activate the policy + auto-provision its Entitlement (`isActive`/`createEntitlement` are QUERY params) |
64
68
  | `POST /services/data/v{version}/connect/sla-management/entitlement-criteria` | **Custom flow** — auto-apply the activated policy's Entitlement to matching records (delegated to `csp-sun/create-entitlement-criteria`); `describe` first and send its exact fields (rejects `filterType`). OOB does not use this — the seeder provisions its own criteria |
65
69
  | `POST /services/data/v{version}/sobjects/Incident` | Create a test Incident |
66
- | `POST /services/data/v{version}/sobjects/BusinessHours` | Phase 2.5 — create an IST (or other-timezone) BusinessHours for the policy/Entitlement (createable; **not** API-deletable) |
67
- | `POST /services/data/v{version}/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) |
70
+ | `POST /services/data/v{version}/sobjects/BusinessHours` | Phase 4A step 1 — create the confirmed Business Hours (described calendar, time-zone 24×7, or org 24×7); createable, **not** API-deletable |
71
+ | `POST /services/data/v{version}/connect/sla-management/sla-policies/<slaId>/milestones/<milestoneId>/actions` | Phase 5 — attach a Warn/Escalate milestone action (delegate via the `create-milestone-action` op) |
68
72
 
69
73
  **API VERSION:** the `v{version}` segment in every URL above (and everywhere in this
70
74
  skill) is resolved to the target org's own current API version at dispatch — resolve it
@@ -75,7 +79,50 @@ org-resolved version is always at or above that floor.
75
79
 
76
80
  ---
77
81
 
78
- ## Phase 0.5 — SLA Management for IT Service prerequisite gate
82
+ ## Phase 1a — IT Service Management enablement gate
83
+
84
+ **New, higher-level org gate — resolve before Phase 1b and before Preflight A below.** "IT Service
85
+ Management" (apiName `service-cloud-itsm-setup`) is a higher-level org gate that sits
86
+ above every per-feature ITSM master toggle, including Master Incident Management (Preflight A). Read
87
+ via the same Setup Discovery Connect API used by Preflight A:
88
+
89
+ ```json
90
+ mcp__headless-360__dispatch_readonly({
91
+ "url": "/services/data/v{version}/connect/setup/discovery/features",
92
+ "method": "GET"
93
+ })
94
+ ```
95
+
96
+ Filter `body.features[]` client-side to the element where `apiName == "service-cloud-itsm-setup"` —
97
+ the **exact** apiName, never a look-alike. Read its `status`. It has two states:
98
+ `ENABLED` / `NOT_ENABLED` — no `NOT_AVAILABLE`. Treat any unexpected status
99
+ value conservatively, the same as a halt.
100
+
101
+ **Status → action:**
102
+
103
+ - `ENABLED` → proceed to Phase 1b.
104
+ - `NOT_ENABLED` → tell the user plainly that IT Service Management is not enabled, then dispatch a
105
+ single `AskUserQuestion`: enable it now (note it's **reversible** — it can be disabled again later)
106
+ or stop.
107
+ - **Enable** →
108
+ ```json
109
+ mcp__headless-360__dispatch({
110
+ "url": "/services/data/v{version}/connect/setup/discovery/feature/service-cloud-itsm-setup/enable",
111
+ "method": "POST"
112
+ })
113
+ ```
114
+ Success returns `201` with `{"success": true}`. If it 4xxs, or the re-read below doesn't
115
+ confirm `ENABLED`, halt, surface the raw error, and point to Setup as the manual fallback. There
116
+ is **no owning SOR** to delegate this write to yet (unlike Preflight A's master pref, which
117
+ delegates to `service-itsm-incident-mgmt-configure`) — dispatch it directly here as a scoped,
118
+ temporary exception to this skill's "delegate every write" rule; swap for a delegate once a
119
+ dedicated SOR for `service-cloud-itsm-setup` exists. Re-read to confirm `status == "ENABLED"`
120
+ before continuing.
121
+ - **Stop** → halt, point to Setup for manual enablement.
122
+
123
+ ---
124
+
125
+ ## Phase 1b — SLA Management for IT Service prerequisite gate
79
126
 
80
127
  **SLA Management for IT Service reads as fully enabled only when BOTH sub-settings are on —
81
128
  Simplified SLA Setup AND SLA Versioning.** In Setup it shows **In Progress** while either is off. Both
@@ -99,8 +146,7 @@ the permanent switch** — an explicit permanence-gated `AskUserQuestion`, kept
99
146
  master-enable ack (see *Ack structure* below). If the user declines the permanence, do **not** complete
100
147
  the gate (SLA Management alone does not satisfy it), and the run **halts**.
101
148
 
102
- This is the root of the versioning false-report defect: the skill turned Versioning on but then
103
- **falsely reported it as off**. The fix: get permanence consent up front, and after each write re-read
149
+ Never report Versioning from a write response alone: get permanence consent up front, and after each write re-read
104
150
  and report the **real** state.
105
151
 
106
152
  ### Read — SLA Management state
@@ -186,8 +232,7 @@ the reads, not a fixed script.
186
232
  completed gate; enable **no further** writes and do not proceed to SLA/milestone setup (a reversible
187
233
  SLA Management enable already made may stand). Say plainly why — Versioning is required and permanent.
188
234
  - **Never** enable Versioning silently or bury the permanent switch in a default — a bare or repeated
189
- "enable SLA" is not consent for the permanent SLA Versioning switch. This is the versioning
190
- false-report bug.
235
+ "enable SLA" is not consent for the permanent SLA Versioning switch.
191
236
  - **After each write, re-read** and report the real, both-on state — never trust the write response.
192
237
  The gate passes only when `get-sla-management-permission` **and** `get-sla-versioning-permission`
193
238
  both return `true`.
@@ -255,11 +300,13 @@ The endpoint returns the full feature catalog (~763 entries, ~1.1 MB) and does n
255
300
  surface it** — the master cannot be enabled here, so there is no ack and no delegate. This is the
256
301
  correct terminal outcome on an unlicensed org (do not pursue Case Management / generic Incident
257
302
  Management as a workaround).
258
- - `NOT_ENABLED` → get an explicit `AskUserQuestion` ack first (per SKILL.md Phase 1 step 1), then
259
- delegate to `service-itsm-incident-mgmt-configure` inline — that skill runs its own confirm-to-write
260
- against `POST .../setup/discovery/feature/service-cloud-itsm-incident/enable` and returns after the
261
- flip. Re-read this step to verify `status == "ENABLED"` before continuing. If the user declines,
262
- halt — every downstream SLA artifact depends on the master being on.
303
+ - `NOT_ENABLED` → get an explicit `AskUserQuestion` ack first (per `references/workflow.md` Phase 3a step 1), phrased
304
+ as the delegate's own confirm payload — `Master Incident Management: NOT_ENABLED → ENABLED` — then
305
+ delegate to `service-itsm-incident-mgmt-configure` inline, which writes
306
+ `POST .../setup/discovery/feature/service-cloud-itsm-incident/enable`. That "yes" **is** the
307
+ delegate's confirm-to-write (same change, same session, nothing written in between) — do **not**
308
+ ask the user a second time. Re-read this step to verify `status == "ENABLED"` before continuing. If
309
+ the user declines, halt — every downstream SLA artifact depends on the master being on.
263
310
 
264
311
  ## Preflight B — SLA fields on the Incident sObject
265
312
 
@@ -281,18 +328,67 @@ than reading the whole body — you only need to confirm those three field names
281
328
 
282
329
  ---
283
330
 
284
- ## Default BusinessHours
331
+ ## Resolve Business Hours
285
332
 
286
333
  ```json
287
334
  mcp__headless-360__dispatch_readonly({
288
335
  "url": "/services/data/v{version}/query",
289
336
  "method": "GET",
290
- "query_params": { "q": "SELECT Id, Name FROM BusinessHours WHERE IsActive = true AND IsDefault = true" }
337
+ "query_params": { "q": "SELECT Id, Name, IsDefault, TimeZoneSidKey, MondayStartTime, MondayEndTime, TuesdayStartTime, TuesdayEndTime, WednesdayStartTime, WednesdayEndTime, ThursdayStartTime, ThursdayEndTime, FridayStartTime, FridayEndTime, SaturdayStartTime, SaturdayEndTime, SundayStartTime, SundayEndTime FROM BusinessHours WHERE IsActive = true" }
338
+ })
339
+ ```
340
+
341
+ Resolve per `references/workflow.md` Phase 3a step 4 (first match wins):
342
+
343
+ - **Named schedule** → case-insensitive `Name` match; exactly one → use it without asking. None →
344
+ `AskUserQuestion`: the active records by name, plus **Create "<name>"** (then ask its time zone,
345
+ days and start/end time, and plan a create (below) under the user's name).
346
+ - **Described calendar** → reuse a record whose `TimeZoneSidKey` and every day's Start/End match the
347
+ description (a day with no hours has both times `null`); none matches → plan a create (below).
348
+ - **Time zone only** ("use IST") → `AskUserQuestion`: 24×7 in that time zone (Recommended) or custom
349
+ hours (then ask days + start/end); resolve the answer as a described calendar. Map the zone to its
350
+ `TimeZoneSidKey` (IST → `Asia/Kolkata`).
351
+ - **Nothing specified** → exactly one `IsDefault=true` → suggested default, no dedicated question.
352
+ - **Zero records** → say so, then `AskUserQuestion`: create a 24×7 schedule, or stop.
353
+ - Any remaining ambiguity (no/several matches, no/several defaults) → `AskUserQuestion` listing the
354
+ active records by name, following the Phase 3b question pattern.
355
+
356
+ Retain the chosen Id internally as the `BusinessHoursId` used on the SLA Policy, Milestone, and
357
+ Entitlement; name the selection in the Phase 3c plan confirmation; never expose the Id.
358
+
359
+ ### Create (Phase 4A step 1 — only when planned and confirmed at Phase 3c)
360
+
361
+ Inline write — no served SOR owns Business Hours writes yet. Use the user's time zone when they named
362
+ one (append it to the name, e.g. `Incident SLA — 24x7 IST`); otherwise read the org time zone first
363
+ (`SELECT TimeZoneSidKey FROM Organization`):
364
+
365
+ ```json
366
+ mcp__headless-360__dispatch({
367
+ "url": "/services/data/v{version}/sobjects/BusinessHours",
368
+ "method": "POST",
369
+ "body": {
370
+ "Name": "Incident SLA — 24x7",
371
+ "IsActive": true,
372
+ "TimeZoneSidKey": "<org TimeZoneSidKey>",
373
+ "MondayStartTime": "00:00:00.000Z", "MondayEndTime": "00:00:00.000Z",
374
+ "TuesdayStartTime": "00:00:00.000Z", "TuesdayEndTime": "00:00:00.000Z",
375
+ "WednesdayStartTime": "00:00:00.000Z", "WednesdayEndTime": "00:00:00.000Z",
376
+ "ThursdayStartTime": "00:00:00.000Z", "ThursdayEndTime": "00:00:00.000Z",
377
+ "FridayStartTime": "00:00:00.000Z", "FridayEndTime": "00:00:00.000Z",
378
+ "SaturdayStartTime": "00:00:00.000Z", "SaturdayEndTime": "00:00:00.000Z",
379
+ "SundayStartTime": "00:00:00.000Z", "SundayEndTime": "00:00:00.000Z"
380
+ }
291
381
  })
292
382
  ```
293
383
 
294
- `body.records[0].Id` is the `BusinessHoursId` used on the SLA Policy, Milestone, and Entitlement.
295
- If `body.records` is empty, stop — the user must create default Business Hours in Setup.
384
+ - **24×7** is encoded as Start = End = `00:00:00.000Z` on a day (the org's seeded `Default` record uses
385
+ exactly this). For a described calendar, set that time zone and the stated windows
386
+ (e.g. `"09:00:00.000Z"`/`"18:00:00.000Z"`), and omit both times on a closed day.
387
+ - **Never** set `IsDefault` and never modify an existing record (including `Default`).
388
+ - `BusinessHours` is **createable but not API-deletable** — disclose at Phase 3c that the record stays
389
+ (deactivate it in Setup if unwanted).
390
+ - Verify: `SELECT Id, Name, IsActive FROM BusinessHours WHERE Id = '<new Id>'` → `IsActive = true`.
391
+ On failure, halt with the raw error before any other write.
296
392
 
297
393
  ---
298
394
 
@@ -305,12 +401,13 @@ mcp__headless-360__dispatch({
305
401
  "body": {
306
402
  "name": "Incident First Response",
307
403
  "description": "Incident First Response",
308
- "recurrenceType": "OneTime"
404
+ "recurrenceType": "none"
309
405
  }
310
406
  })
311
407
  ```
312
408
 
313
- `recurrenceType` = `OneTime` | `Recurring`. Success: `body.id` is the new MilestoneType Id. If
409
+ `recurrenceType` takes the enum-id form: `none` (reads back "No Recurrence"), `recursIndependently`,
410
+ or `recursChained`; any other value is silently coerced to `none`. Success: `body.id` is the new MilestoneType Id. If
314
411
  absent, the create failed — surface `body`.
315
412
 
316
413
  ---
@@ -327,9 +424,7 @@ mcp__headless-360__dispatch({
327
424
  "processType": "Incident",
328
425
  "businessHourId": "<BusinessHoursId>",
329
426
  "createdDateEntryCriteria": true,
330
- "closedExitCriteria": true,
331
- "active": false,
332
- "versionDefault": true
427
+ "closedExitCriteria": true
333
428
  }
334
429
  })
335
430
  ```
@@ -345,7 +440,8 @@ mcp__headless-360__dispatch_readonly({
345
440
  })
346
441
  ```
347
442
 
348
- **Custom flow creates the policy inactive** (`active: false`) — activation is a separate, explicit
443
+ **Custom flow creates the policy inactive** (the create always lands inactive; there is no `active`
444
+ field to send) — activation is a separate, explicit
349
445
  step so the Entitlement is **auto-provisioned**. After the milestones are attached, activate via the
350
446
  `csp-sun/activate-sla-policy` leaf:
351
447
 
@@ -397,7 +493,7 @@ mcp__headless-360__dispatch({
397
493
  })
398
494
  ```
399
495
 
400
- **`startTimeBasedOn`** controls when the timer starts. Send **`"MILESTONE_CRITERIA"`** (matches OOB and every default pattern) to start the clock when the milestone's ACTIVE criteria first match. It is a free string with two recognized values — **`MILESTONE_CRITERIA`** (criteria-based / dynamic start) and **`SLA_PROCESS`** (the fallback); any other value silently defaults to the `SLA_PROCESS` behavior (no error). The fallback anchors the timer to the **Incident's `SlaStartDate`** (→ its `CreatedDate` if `SlaStartDate` is null) — **not** the SLA-process record's created date. **This choice is not runtime-verifiable in the standard verify flow:** for a test Incident that matches the SLA at creation, both settings compute the same `TargetDate` (≈ `SlaStartDate + timeTrigger`) — they diverge only when the criteria first match *after* creation (e.g. a later field change), which the Phase 3 test does not exercise. So send the OOB value and rely on it; there is no Phase-3 assertion that distinguishes the two (unlike the ACTIVE criterion, whose effect **is** observable via tiering — see below). `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. Success: `body.id` is the new Milestone Id.
496
+ **`startTimeBasedOn`** controls when the timer starts. Send **`"MILESTONE_CRITERIA"`** (matches OOB and every default pattern) to start the clock when the milestone's ACTIVE criteria first match. It is a free string with two recognized values — **`MILESTONE_CRITERIA`** (criteria-based / dynamic start) and **`SLA_PROCESS`** (the fallback); any other value silently defaults to the `SLA_PROCESS` behavior (no error). The fallback anchors the timer to the **Incident's `SlaStartDate`** (→ its `CreatedDate` if `SlaStartDate` is null) — **not** the SLA-process record's created date. **This choice is not runtime-verifiable in the standard verify flow:** for a test Incident that matches the SLA at creation, both settings compute the same `TargetDate` (≈ `SlaStartDate + timeTrigger`) — they diverge only when the criteria first match *after* creation (e.g. a later field change), which the Phase 6 test does not exercise. So send the OOB value and rely on it; there is no Phase-6 assertion that distinguishes the two (unlike the ACTIVE criterion, whose effect **is** observable via tiering — see below). `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. Success: `body.id` is the new Milestone Id.
401
497
 
402
498
  **`milestoneState` MUST be UPPERCASE and comes from a fixed set — this is load-bearing.** Valid values are **`ACTIVE`**, **`COMPLETE`**, **`PAUSE`**, **`UNPAUSE`** (there is **no `CANCEL`** state). The server compares `milestoneState` against `"ACTIVE"` **case-sensitively**, so `"Active"`/`"active"` (or any wrong case) **silently fails to register the ACTIVE criterion** — the create still returns `201 success:true`, but the priority/entry filter is never written and the Setup UI shows blank Activation Criteria. The milestone loses its Priority gate, so **in practice every Incident engages the lowest-`order` milestone of that MilestoneType regardless of its Priority** — a priority-tiered policy collapses to one tier. Use `ACTIVE` for the engagement (Priority) criterion and `COMPLETE` for the completion (Status) criterion; never send `CANCEL` (once the `ACTIVE` Priority criterion is correct it gates engagement, making a cancel criterion redundant).
403
499
 
@@ -405,12 +501,12 @@ mcp__headless-360__dispatch({
405
501
 
406
502
  ---
407
503
 
408
- ## Milestone Actions (Phase 2.5 — Warn / Escalate)
504
+ ## Milestone Actions (Phase 5 — Warn / Escalate)
409
505
 
410
506
  A **milestone action** fires automation at a checkpoint of an existing milestone — a **Warning**
411
507
  (before target), a **Violation** (at/after target), or a **Success** (on completion). This is how the
412
508
  skill implements "warn at 75%, escalate on breach". It runs **only** when the user asked to
413
- warn/escalate/notify, **after** the milestones exist (Phase 2 or Phase 2-OOB).
509
+ warn/escalate/notify, **after** the milestones exist (Phase 4A or Phase 4B).
414
510
 
415
511
  **Scope — apply to every milestone the user named for that policy.** "Warn at 75%, escalate on breach"
416
512
  attaches to **each** milestone the request scopes it to (e.g. a `15-min response` *and* a `2-hour
@@ -460,7 +556,7 @@ offsetBeforeTarget = round( milestoneTargetMinutes × (1 − X/100) )
460
556
 
461
557
  "Escalate **on breach**" → a Violation with `timeLength: 0`.
462
558
 
463
- ### Milestone-action bodies (Field Update; example shapes, pending live verification)
559
+ ### Milestone-action bodies (Field Update; example shapes)
464
560
 
465
561
  **Default action is a Field Update** — self-contained, no org dependencies. `actionFlow` returns an
466
562
  opaque `201 / success:false / INTERNAL_SERVER_ERROR` on empty-flow auto-create in some orgs — avoid it
@@ -517,8 +613,8 @@ WHERE Id IN (<the actionMapping ids from the create responses>)` for the default
517
613
  (other action types map to `WorkflowAlert` / `Task` / etc.) — but that confirms **existence only**, not
518
614
  the attachment or offset, so it is an optional debugging aid, not the verification. There is also **no
519
615
  clean headless delete**. Because the attachment can't be read back, the full action set **must be
520
- confirmed before writing**. Up-front authorization (the Phase 1.4 skip condition (c)) waives the
521
- interactive `AskUserQuestion` re-ask exactly as Phase 1.5 does, but the set must still be **narrated**
616
+ confirmed before writing**. Up-front authorization (the Phase 3b skip condition (c)) waives the
617
+ interactive `AskUserQuestion` re-ask exactly as Phase 3c does, but the set must still be **narrated**
522
618
  before the writes; verification is body-based, not a GET.
523
619
 
524
620
  ### "IST business hours" is a policy-level BusinessHours, not an action field
@@ -527,19 +623,21 @@ Milestone actions carry **no** timezone/business-hours attribute. "IST business
527
623
  `BusinessHours` record (`TimeZoneSidKey: "Asia/Kolkata"` + weekly windows) attached at the **policy /
528
624
  Entitlement** level (`Entitlement.BusinessHoursId`). Resolve-then-create:
529
625
 
530
- 1. Look up an existing BusinessHours with `TimeZoneSidKey = 'Asia/Kolkata'`; **reuse** if found.
531
- 2. Else create one — `POST /sobjects/BusinessHours` (`Name`, `TimeZoneSidKey: "Asia/Kolkata"`,
532
- default Mon–Fri 09:00–18:00 windows). `BusinessHours` is **createable but not API-deletable**, so
533
- confirm before creating; never mutate the org `Default` record and never set `IsDefault`.
534
- 3. Attach via the policy/Entitlement `BusinessHoursId`.
626
+ 1. Look up an existing BusinessHours with `TimeZoneSidKey = 'Asia/Kolkata'` and matching windows;
627
+ **reuse** if found.
628
+ 2. Else create one per **Resolve Business Hours → Create** (`TimeZoneSidKey: "Asia/Kolkata"`, default
629
+ Mon–Fri 09:00–18:00 windows), confirmed at Phase 3c.
630
+ 3. Attach via the policy/Entitlement `BusinessHoursId`. (Custom only — the predefined seeder always
631
+ uses the org default Business Hours.)
535
632
 
536
- **Caveat — read it live and disclose:** if the org has `ignoreMilestoneBusinessHours = true`, milestone
537
- SLA timers run **24/7** and ignore business hours, so an IST BusinessHours is recorded but does **not**
538
- shift the milestone clock. State this plainly instead of implying IST changed the timers.
633
+ **Do not misread `ignoreMilestoneBusinessHours`.** That Entitlement setting only changes how the
634
+ milestone tracker *displays* time remaining (actual hours when `true`, business hours when `false`).
635
+ Milestone target dates still follow the policy's Business Hours, so never tell the user the timers run
636
+ 24/7 because of it.
539
637
 
540
638
  ---
541
639
 
542
- ## Predefined Incident Policy (Phase 0.6 detect + Phase 2-OOB seed)
640
+ ## Predefined Incident Policy (Phase 2 detect + Phase 4B seed)
543
641
 
544
642
  The out-of-box **"Standard Support for Incidents"** policy is what Salesforce seeds from Setup's
545
643
  "Create Predefined Policies" step (Incident process type only). That seeder — the SLA Settings page's
@@ -547,9 +645,9 @@ The out-of-box **"Standard Support for Incidents"** policy is what Salesforce se
547
645
  `/headless/invoke/platform/slasettings/*`, so the skill invokes the **real seeder in ONE call** rather
548
646
  than replicating its output. The seeder builds the entire **active** bundle itself — policy + 2
549
647
  MilestoneTypes + 6 milestones (Critical/High per-tier, Moderate+Low merged) + Entitlement + auto-apply
550
- criteria — the same core out-of-box seed data, with Core's own Priority/Status handling. (Route
551
- live-proven for both read and write; the former hand-rebuilt replica over `/connect/sla-management/*`
552
- plus the manual `POST /sobjects/Entitlement` is retired.)
648
+ criteria — the same core out-of-box seed data, with Core's own Priority/Status handling. (The former
649
+ hand-rebuilt replica over `/connect/sla-management/*` plus the manual `POST /sobjects/Entitlement`
650
+ is retired.)
553
651
 
554
652
  ### Detect first (no server idempotency → mandatory)
555
653
 
@@ -564,8 +662,9 @@ mcp__headless-360__dispatch_readonly({
564
662
  ```
565
663
 
566
664
  It returns a **lowercase-keyed** map, e.g. `{"incident": true}` (keys: `incident`, `problem`,
567
- `changeRequest`; a key is `true` when that type's default is already seeded). If `incident` is `true`,
568
- the OOB policy is already present — report it and do **not** re-seed. (Fallback: SOQL `SELECT Id, Name
665
+ `changeRequest`; a key is `true` when that type's default is already seeded). An org where nothing has
666
+ been seeded yet returns an empty map `{}` — a **missing** key means not seeded, same as `false`. If
667
+ `incident` is `true`, the OOB policy is already present — report it and do **not** re-seed. (Fallback: SOQL `SELECT Id, Name
569
668
  FROM SlaProcess WHERE SobjectType = 'Incident' AND Name = 'Standard Support for Incidents'`.)
570
669
 
571
670
  ### Seed (only if not already present)
@@ -592,13 +691,32 @@ mcp__headless-360__dispatch({
592
691
 
593
692
  Re-read the existence map (`GET /headless/invoke/platform/slasettings`) and confirm `incident: true`,
594
693
  then SOQL `SlaProcess` for **"Standard Support for Incidents"** with `IsActive = true` (do not trust the
595
- write body). Then verify runtime engagement per **Verify SLA engagement** below with a **Moderate/Low**
694
+ write body), selecting `BusinessHours.Name`. Report that Business Hours by name — the seeder takes no
695
+ Business Hours input and attaches the org's active default (`IsDefault = true`), or none if there is
696
+ no active default; say "no Business Hours" plainly in that case. Then verify runtime engagement per **Verify SLA engagement** below with a **Moderate/Low**
596
697
  test Incident — its `EntityMilestone` must land on the 240/960 tier, not 30/120 (Critical is order-1,
597
- the collapse fallback, so it can't detect a mis-tiered seed). Then **STOP** — do not offer custom.
698
+ the collapse fallback, so it can't detect a mis-tiered seed), subject to the stopping rule there. Then **STOP** — do not offer custom.
598
699
  Narrate the policy by name, never its Id (Output contract).
599
700
 
600
701
  ---
601
702
 
703
+ ## Priority matrix flag (Phase 2 note + Phase 6 stopping rule)
704
+
705
+ ```json
706
+ mcp__headless-360__dispatch_readonly({
707
+ "url": "/services/data/v{version}/setup/org/preferences/IncPriorityMatrixEnabled",
708
+ "method": "GET"
709
+ })
710
+ → { "isPreferenceEnabled": true | false }
711
+ ```
712
+
713
+ `false` → the Impact × Urgency matrix is off and every Incident gets the org's default priority, so a
714
+ priority-tiered policy (the predefined one, or Custom Priority-tiered) only fires that tier's
715
+ milestones. Warn the user and point to `service-itsm-incident-priority-configure`; never enable the
716
+ matrix from this skill (that skill owns the write). Read-only — not a gate.
717
+
718
+ ---
719
+
602
720
  ## Verify SLA engagement
603
721
 
604
722
  Create a test Incident. **`Priority` is NOT directly writable on `Incident`** — the field is
@@ -654,7 +772,13 @@ When `SlaStartDate` is populated, `TargetDate` should equal `SlaStartDate + time
654
772
  `EntityMilestone.TargetResponseInMins` should equal the target tier's `timeTrigger`. First confirm the
655
773
  **derived** `Priority` on the Incident is the tier you intended (from the `Impact`/`Urgency` you set) —
656
774
  if the org's matrix mapped your `Impact`/`Urgency` to a different Priority, adjust them and recreate
657
- rather than reading the assertion against the wrong tier.
775
+ **once** rather than reading the assertion against the wrong tier.
776
+
777
+ **Stopping rule.** If the matrix flag (above) is `false`, create **one** test Incident only — every
778
+ input derives the default priority. If the flag is `true` but the derived `Priority` is still the
779
+ order-1 tier after one adjustment, stop. Either way report: the SLA engages (the `EntityMilestone` +
780
+ `TargetDate`), the other tiers were **not** checked, why, and that
781
+ `service-itsm-incident-priority-configure` configures the matrix. Never loop on recreates.
658
782
 
659
783
  ---
660
784
 
@@ -671,4 +795,4 @@ rather than reading the assertion against the wrong tier.
671
795
  | OOB seed `selectedOptions` casing | The `save-selected-options` values MUST be **lowercase** (`incident`/`problem`/`changeRequest`), matching the existence-map keys. The capitalized `Incident` form returns a server-side **`500`** — the single most common OOB failure; the describe metadata's `{Incident,Problem,ChangeRequest}` casing is misleading. |
672
796
  | OOB seed has no idempotency | `save-selected-options` does not dedupe — re-seeding "Standard Support for Incidents" duplicates every artifact. Detect first via `GET /headless/invoke/platform/slasettings` (existence map; `incident: true` = already seeded) before seeding. |
673
797
  | OOB uses the seeder, not the Connect activate PATCH | The **OOB seed** does one `save-selected-options` call that seeds an already-active policy + auto-provisions its Entitlement — it never touches the Connect activate PATCH. The **custom flow** activates via the `csp-sun/activate-sla-policy` leaf (`isActive`+`createEntitlement` query params) — the no-500 activation path (a `200` with a returned `entitlementId` is the success shape). |
674
- | Never leak a record Id (SKILL.md Output contract) | In **every** user-facing message — interim narration *and* the final report, incl. "created milestone …" / "policy created …" / "reusing existing … →" progress lines — refer to the Phase-3 test Incident by its **`IncidentNumber`** (the verify SOQL selects it) and milestones/policy by their **name** — never the 15/18-char record Id (full **or masked**, e.g. `557VW…R3XVYA0`) or a `triggerId`. This covers **detected/reused** artifacts too — no `→ <Id>` "proof of reuse". Ids stay internal (chaining only). |
798
+ | Never leak a record Id (SKILL.md Output contract) | In **every** user-facing message — interim narration *and* the final report, incl. "created milestone …" / "policy created …" / "reusing existing … →" progress lines — refer to the Phase-6 test Incident by its **`IncidentNumber`** (the verify SOQL selects it) and milestones/policy by their **name** — never the 15/18-char record Id (full **or masked**, e.g. `557VW…R3XVYA0`) or a `triggerId`. This covers **detected/reused** artifacts too — no `→ <Id>` "proof of reuse". Ids stay internal (chaining only). |