@salesforce/afv-skills 1.50.0 → 1.52.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 (41) hide show
  1. package/package.json +1 -1
  2. package/skills/experience-ui-bundle-deploy/SKILL.md +43 -2
  3. package/skills/experience-ui-bundle-deploy/references/config-scaffold.md +16 -3
  4. package/skills/experience-ui-bundle-deploy/references/logout-url.md +97 -0
  5. package/skills/experience-ui-bundle-deploy/scripts/set-logout-url.mjs +304 -0
  6. package/skills/experience-ui-bundle-localize/SKILL.md +107 -90
  7. package/skills/experience-ui-bundle-localize/references/angular/check-i18n-wired.sh +159 -0
  8. package/skills/experience-ui-bundle-localize/references/angular/i18n-setup.md +250 -0
  9. package/skills/experience-ui-bundle-localize/references/angular/interpolation.md +156 -0
  10. package/skills/experience-ui-bundle-localize/references/angular/localize.md +111 -0
  11. package/skills/experience-ui-bundle-localize/references/{gotchas.md → common/gotchas.md} +27 -43
  12. package/skills/experience-ui-bundle-localize/references/{label-xml.md → common/label-xml.md} +27 -17
  13. package/skills/experience-ui-bundle-localize/references/common/platform-sdk-i18n.md +169 -0
  14. package/skills/experience-ui-bundle-localize/references/{verifying.md → common/verifying.md} +26 -16
  15. package/skills/experience-ui-bundle-localize/{scripts → references/react}/check-i18n-wired.sh +8 -3
  16. package/skills/experience-ui-bundle-localize/references/{i18n-setup.md → react/i18n-setup.md} +48 -10
  17. package/skills/experience-ui-bundle-localize/references/{interpolation.md → react/interpolation.md} +4 -4
  18. package/skills/experience-ui-bundle-localize/references/react/localize.md +76 -0
  19. package/skills/experience-ui-bundle-localize/scripts/check-manifest-registered.sh +92 -24
  20. package/skills/experience-ui-bundle-localize/scripts/detect-framework.sh +73 -0
  21. package/skills/experience-ui-bundle-site-generate/SKILL.md +1 -1
  22. package/skills/field-service-data-capture-form-deployer-configure/SKILL.md +1 -1
  23. package/skills/field-service-data-capture-form-deployer-configure/references/flow-metadata-json.md +1 -1
  24. package/skills/field-service-data-capture-form-editor-configure/SKILL.md +1 -1
  25. package/skills/field-service-data-capture-reference-configure/SKILL.md +28 -15
  26. package/skills/field-service-foundation-setup-designer-get/SKILL.md +1 -1
  27. package/skills/field-service-mobile-branding-configure/SKILL.md +1 -1
  28. package/skills/field-service-objective-designer-configure/SKILL.md +381 -64
  29. package/skills/field-service-prework-brief-deployer-configure/SKILL.md +566 -3
  30. package/skills/field-service-scheduling-policy-designer-query/SKILL.md +1097 -57
  31. package/skills/field-service-sobject-create-configure/SKILL.md +222 -7
  32. package/skills/field-service-voice-to-form-configure/SKILL.md +11 -11
  33. package/skills/field-service-work-rule-designer-configure/SKILL.md +92 -107
  34. package/skills/service-digital-engagement-channel-configure/SKILL.md +20 -37
  35. package/skills/service-digital-engagement-channel-configure/assets/messaging_channel_template.xml +3 -2
  36. package/skills/service-digital-engagement-channel-configure/examples/asa_agent_channel.xml +4 -4
  37. package/skills/service-helpagent-coordinate/SKILL.md +37 -29
  38. package/skills/service-helpagent-coordinate/assets/help-agent-spec.md +33 -28
  39. package/skills/service-helpagent-coordinate/references/agent-script.md +4 -1
  40. package/skills/service-helpagent-coordinate/references/channel-voice.md +1 -1
  41. package/skills/service-helpagent-coordinate/references/channel-web-chat.md +10 -12
@@ -5,29 +5,48 @@ user-invocable: false
5
5
  metadata:
6
6
  version: "1.0"
7
7
  domains: ["Field Service"]
8
+ cliTools:
9
+ - tool: ["sf"]
10
+ semver: ">=2.0.0"
8
11
  ---
9
12
 
13
+ # Managing Sfs Sobject Create
14
+
15
+ ## When to Use This Skill
16
+
17
+ Create sObject records via Headless 360 REST API. Describes the flow (describe → query → create), Field Service data model DAG, field requirements, insertion order, and common pitfalls. Reference when creating Skill, WorkType, SkillRequirement, or other Field Service sObjects.
18
+
19
+ ## Workflow
20
+
10
21
  # Create an sObject record via headless-360
11
22
 
12
23
  **Be helpful** — understand business context before creating records. Consider the business domain of the sObject being created and iterate through short, structured questions (ask/why/impact) until no ambiguities remain that would change what gets created. Skip questions when answers are already obvious from context or existing data.
13
24
 
14
25
  ## Flow
15
26
 
16
- 1. **Describe** — `dispatch_readonly` GET `/services/data/v67.0/sobjects/<SObject>/describe`
17
- 2. **Query existing records** — learn the org's shape before writing.
18
- `dispatch_readonly` GET `/services/data/v67.0/query`,
27
+ ### Phase 1: **Describe** — `dispatch_readonly` GET `/services/data/v67.0/sobjects/<SObject>/describe`
28
+
29
+
30
+
31
+ ### Phase 2: **Query existing records** — learn the org's shape...
32
+
33
+ `dispatch_readonly` GET `/services/data/v67.0/query`,
19
34
  `queryParams.q = "SELECT <required + picklist fields> FROM <SObject> ORDER BY CreatedDate DESC LIMIT 20"`.
20
35
  Use it to: match naming/value conventions, see which optional fields are actually populated,
21
36
  catch duplicates, and confirm write access before spending a create.
22
- 3. **Create** — `dispatch` POST to create records. Single record → `/services/data/v67.0/sobjects/<SObject>` with body. Multiple related records (DAG) → `/services/data/v67.0/composite/graph` to batch-create with dependency references in one transaction. Success → `201` with id(s). Failure → non-2xx with `errorCode` + `message` — act on that.
37
+
38
+ ### Phase 3: **Create** — `dispatch` POST to create records. Single...
39
+
40
+
23
41
 
24
42
  ## Data model DAG
25
43
 
26
- These examples show Field Service relationship patterns, but the same approach applies to any sObject based on its data shape:
44
+ Example (Field Service junction pattern — same pattern applies to any sObject DAG based on the data shape):
27
45
 
28
46
  ```text
29
- Skill + WorkType → SkillRequirement WorkType + Product2 → ProductRequired
30
- OperatingHours → ServiceTerritory + TimeSlot
47
+ Skill (0C5) WorkType (08q) ← roots (parallel)
48
+ └──────────┬──────────┘
49
+ SkillRequirement (0Hx) ← junction (last)
31
50
  ```
32
51
 
33
52
  ## Fields and insertion order
@@ -54,3 +73,199 @@ to see conventions and dupes. Then create with the derived body, e.g.
54
73
  { "url": "/services/data/v67.0/sobjects/WorkType", "method": "POST",
55
74
  "body": { "Name": "Standard Repair", "EstimatedDuration": 2 } }
56
75
  ```
76
+
77
+ ─────
78
+ **Runtime context (Headless 360 / agentic):** When this skill runs in the Headless 360 / agentic context, prefer the platform dispatch tool (``dispatch`` in the hosted Headless 360 MCP; ``dispatch`` in the local-dev MCP) over CLI tools (``sf project deploy``, ``sfdx``, shell commands) when possible. The operations available to you are listed below in ``steps:``; each has been verified against the live org. Call the dispatch tool against the canonical paths. CLI fallback is acceptable only when no API path exists for a given capability.
79
+
80
+ ## Critical Constraints
81
+
82
+ **Preconditions:**
83
+
84
+ - Target sObject is createable and not on the sObject-REST block list. (check: `GET /services/data/v67.0/sobjects/{N}/describe returns `createable: true` at the top level. A `CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY` on POST means the sObject blocks base REST writes (e.g. `ExternalDataSource`, `CustomPermission`) — switch to Tooling or Metadata API.`)
85
+ - Gateway user has object CRUD + relevant FLS for the required createable fields. (check: `400 / 403 with `INSUFFICIENT_ACCESS_OR_READONLY` on POST → CRUD/FLS gap, not a payload bug. Grant the user's profile / permset the Create on the entity and Edit-access on every field in the body.`)
86
+ - For composite/graph transactions, the caller has independently topo-sorted parents before children within each graph node's `records`. (check: ``referenceId`s used with `@{...}` MUST refer to a record earlier in the same graph. Wrong ordering surfaces as `INVALID_REFERENCE_ID` on the child node, and the entire graph rolls back atomically.`)
87
+
88
+ ## Operations Reference
89
+
90
+ Operations grouped by purpose. Use these as the building blocks for the workflows above.
91
+
92
+ ### Summary
93
+
94
+ | Operation | Purpose | Status | Call | Depends on |
95
+ |-----------|---------|--------|------|------------|
96
+ | `describe-sobject` | read | — | `GET /services/data/v67.0/sobjects/{SObjectName}/describe` | — |
97
+ | `query-existing-records` | read | — | `GET /services/data/v67.0/query` | `describe-sobject` |
98
+ | `create-sobject-record` | write | — | `POST /services/data/v67.0/sobjects/{SObjectName}` | `describe-sobject` |
99
+ | `composite-graph-create` | write | — | `POST /services/data/v67.0/composite/graph` | `describe-sobject` |
100
+ | `update-sobject-record` | write | — | `PATCH /services/data/v67.0/sobjects/{SObjectName}/{Id}` | `create-sobject-record` |
101
+ | `delete-sobject-record` | write | — | `DELETE /services/data/v67.0/sobjects/{SObjectName}/{Id}` | — |
102
+
103
+ ### Dependency graph
104
+
105
+ ```mermaid
106
+ graph TD
107
+ describe_sobject["describe-sobject (read)"]
108
+ query_existing_records["query-existing-records (read)"]
109
+ create_sobject_record["create-sobject-record (write)"]
110
+ composite_graph_create["composite-graph-create (write)"]
111
+ update_sobject_record["update-sobject-record (write)"]
112
+ delete_sobject_record["delete-sobject-record (write)"]
113
+ describe_sobject --> query_existing_records
114
+ describe_sobject --> create_sobject_record
115
+ describe_sobject --> composite_graph_create
116
+ create_sobject_record --> update_sobject_record
117
+ ```
118
+
119
+ ### Read operations
120
+
121
+ #### `describe-sobject`
122
+
123
+ Fetch the field catalog for {SObjectName}. Scan `fields[]` for
124
+ `createable:true`; hard-required fields are those also with
125
+ `nillable:false` and `defaultedOnCreate:false`. `type:"reference"`
126
+ fields are FKs — hard edges when `nillable:false`. Base sObject
127
+ CRUD is intentionally OUT of the discover corpus (skill §Pitfalls);
128
+ agents must skip discover and call describe directly.
129
+
130
+ **Call:** `GET /services/data/v67.0/sobjects/{SObjectName}/describe`
131
+
132
+ **Inputs:**
133
+
134
+ - `SObjectName` *(`string`)* — API name of the sObject (e.g. WorkType, Skill, SkillRequirement). Path segment.
135
+
136
+ **Output:** SObjectDescribeSObjectResult. Load-bearing keys: `createable`, `updateable`, `deletable`, `fields[]` (each with `name`, `type`, `createable`, `nillable`, `defaultedOnCreate`, `referenceTo[]`, `picklistValues[]`). Payload is large (>60KB for WorkType) — filter to `createable:true` fields before reasoning.
137
+
138
+ #### `query-existing-records`
139
+
140
+ Warm-read a small window of existing rows to match naming
141
+ conventions, spot dupes, and confirm write access before spending
142
+ a create. Skill §Flow.2 suggested SOQL:
143
+ `SELECT <required + picklist fields> FROM <SObject>
144
+ ORDER BY CreatedDate DESC LIMIT 20`.
145
+
146
+ **Call:** `GET /services/data/v67.0/query`
147
+
148
+ **Inputs:**
149
+
150
+ - `q` *(`string`)* — SOQL query. Pass via `queryParams.q` (URL-encoded on the wire). LIMIT 20 or fewer is the recommended window for convention scanning.
151
+
152
+ **Depends on:** `describe-sobject`
153
+
154
+ **Output:** `{totalSize, done, records: [<row>]}`. `records[]` is the shape an agent scans for conventions. `done:false` + `nextRecordsUrl` surface when > 200 rows — irrelevant at LIMIT 20.
155
+
156
+ ### Write operations
157
+
158
+ #### `create-sobject-record`
159
+
160
+ Create ONE record. Body carries only fields that were
161
+ `createable:true` on describe. For DAGs (parents + children +
162
+ junctions), prefer composite/graph so all rows land atomically
163
+ in one transaction. 201 → `{id, success, errors:[]}`; non-2xx
164
+ returns `[{errorCode, message, fields:[]}]`.
165
+
166
+ **Call:** `POST /services/data/v67.0/sobjects/{SObjectName}`
167
+
168
+ **Inputs:**
169
+
170
+ - `SObjectName` *(`string`)* — API name of the sObject (path segment).
171
+ - `body` *(`object`)* — Field/value map. Only include fields with `createable:true` on describe; omit `defaultedOnCreate:true` fields (the platform fills them).
172
+
173
+ **Depends on:** `describe-sobject`
174
+
175
+ **Output:** 201 → `{id: "<15/18-char id>", success: true, errors: []}`. 4xx → array of `{errorCode, message, fields}`.
176
+
177
+ **Rollback:** delete-sobject-record
178
+
179
+ **Notes:** ERROR CONTRACT:
180
+ - `CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY` → sObject blocks base
181
+ REST writes; switch to Tooling / Metadata API. Common for
182
+ `ExternalDataSource`, `CustomPermission`.
183
+ - `INSUFFICIENT_ACCESS_OR_READONLY` → CRUD/FLS/sharing gap on
184
+ the gateway user; don't retry the same body.
185
+ - `REQUIRED_FIELD_MISSING` → re-check describe filter (some
186
+ fields are createable+nillable:false only in specific record
187
+ types).
188
+ - `INVALID_FIELD_FOR_INSERT_UPDATE` → field is not
189
+ `createable:true`; drop from body.
190
+
191
+ #### `composite-graph-create`
192
+
193
+ Atomically create a DAG of related records in one transaction.
194
+ Skill §Data-model-DAG example: Skill + WorkType (roots) →
195
+ SkillRequirement (junction). Use `referenceId` on each record
196
+ and `@{parentRef.id}` in a child's FK field to bind at write
197
+ time. Success returns 200 with per-node compositeResponse[]
198
+ entries carrying per-child 201s. Any failure rolls back the
199
+ ENTIRE graph.
200
+
201
+ **Call:** `POST /services/data/v67.0/composite/graph`
202
+
203
+ **Inputs:**
204
+
205
+ - `body` *(`object`)* — `{graphs: [{graphId, compositeRequest: [{referenceId,
206
+ method:"POST", url:"/services/data/v67.0/sobjects/<N>",
207
+ body:{...}}, ...]}]}`. Multiple graphs may share one call;
208
+ each isolates atomicity.
209
+
210
+ **Depends on:** `describe-sobject`
211
+
212
+ **Output:** 200 → `{graphs: [{graphId, graphResponse: {compositeResponse: [{body:{id, success, errors}, httpHeaders, httpStatusCode, referenceId}]}, isSuccessful}]}`. `isSuccessful:false` + per-child 4xx bodies on any failure.
213
+
214
+ **Rollback:** delete-sobject-record
215
+
216
+ **Notes:** ERROR CONTRACT:
217
+ - `INVALID_REFERENCE_ID` → child references a `referenceId`
218
+ that appears LATER in the array or doesn't exist. Topo-sort
219
+ the compositeRequest[] parents-first.
220
+ - `LIMIT_EXCEEDED` → composite/graph caps at 500 records per
221
+ graph and 75 graphs per call.
222
+ - `MIXED_DML_OPERATION` → **the graph mixes setup-object
223
+ sObjects (e.g. `Skill`, `Group`, `User`, `Permission*`) with
224
+ non-setup sObjects (e.g. `WorkType`, `Account`, `Contact`)
225
+ in one transaction — the platform forbids this even inside
226
+ composite/graph.** Split into two calls: create setup-side
227
+ in call 1, capture the id, then create non-setup-side +
228
+ junction referencing that id in call 2. The skill's
229
+ Skill+WorkType+SkillRequirement example REQUIRES this split.
230
+ - Any HTTP 4xx on ANY child → the graph's entire
231
+ compositeResponse rolls back; sibling children report
232
+ `PROCESSING_HALTED` and DELETE cleanup is unnecessary for
233
+ a failed graph.
234
+
235
+ #### `update-sobject-record`
236
+
237
+ Field-level update on an existing record. Use for late-bound
238
+ `nillable:true` reference attachment (skill §Fields-and-
239
+ insertion-order) or corrections. PATCH is field-merge, not
240
+ full-replacement: only fields in the body change; omitted
241
+ fields are untouched. 204 on success (no response body).
242
+
243
+ **Call:** `PATCH /services/data/v67.0/sobjects/{SObjectName}/{Id}`
244
+
245
+ **Inputs:**
246
+
247
+ - `SObjectName` *(`string`)*
248
+ - `Id` *(`string`)* — 15- or 18-char record id (path segment).
249
+ - `body` *(`object`)* — Field/value map. Only include fields with `updateable:true` on describe.
250
+
251
+ **Depends on:** `create-sobject-record`
252
+
253
+ **Output:** 204 No Content on success. 4xx → same `[{errorCode, message, fields}]` shape as POST.
254
+
255
+ #### `delete-sobject-record`
256
+
257
+ Delete a record. Rollback target for create-sobject-record
258
+ (single) and composite-graph-create (children where the
259
+ transaction succeeded but a downstream verify failed).
260
+ 204 on success. Note: composite/graph atomically rolls back
261
+ on failure — DELETE is only needed after a SUCCESSFUL graph
262
+ that a later validation rejects.
263
+
264
+ **Call:** `DELETE /services/data/v67.0/sobjects/{SObjectName}/{Id}`
265
+
266
+ **Inputs:**
267
+
268
+ - `SObjectName` *(`string`)*
269
+ - `Id` *(`string`)*
270
+
271
+ **Output:** 204 No Content. 404 → id already gone (idempotent); treat as success.
@@ -29,7 +29,7 @@ This skill walks the complete setup for both, in the order Salesforce documents
29
29
  The skill is idempotent. Re-running on an already-configured org applies zero changes.
30
30
 
31
31
  > **Runtime contract:** every org interaction in this skill is a REST call
32
- > dispatched through the Codey runtime (`execute_api` locally / the hosted
32
+ > dispatched through the Codey runtime (`dispatch` locally / the hosted
33
33
  > Headless 360 MCP in shared surfaces). This skill has **no dependency on the
34
34
  > execution environment** — no `sf` CLI, no shell scripts, no local Python, no
35
35
  > `jq`, no temp files, no metadata deploy, no Apex. Detection is a set of REST
@@ -44,7 +44,7 @@ The skill is idempotent. Re-running on an already-configured org applies zero ch
44
44
 
45
45
  ## Platform Notes
46
46
 
47
- - All API paths use `vXX.0` — pin to the org's **current** API version (query `GET /services/data` and use the highest `version`), NOT a fixed floor. This matters for the Step 3 feature test specifically: the `PermissionsFieldServiceVoiceTo*` describe columns only surface at a recent API version. On a live org the columns were **absent** from the `PermissionSet` describe at v62.0/v64.0 but **present** at v68.0 — pinning to an old version produces a false "feature not licensed → Stop" negative. Use the org's latest version so the describe reflects the beta perms. v62.0 is a hard floor only (the V2F Beta assumes a recent release); it is not a safe version for the describe test.
47
+ - All API paths use `vXX.0` — pin to the org's current API version (v62.0 or later; the V2F Beta assumes a recent release).
48
48
  - Endpoints marked **Tooling** dispatch to `/services/data/vXX.0/tooling/...`; the rest are the core Data API (`/services/data/vXX.0/...`).
49
49
  - The Codey runtime resolves and refreshes the connected org and mints tokens on demand — this skill never manages org aliases, instance URLs, or access tokens.
50
50
  - A few setup steps are genuinely clicks-only in **Setup** (the Einstein base-setup wizard org pref, the per-form LLM Targetable flag). For those the skill surfaces the exact Setup deeplink for the admin to click; it never tries to script them.
@@ -76,7 +76,7 @@ Before running the setup sequence, confirm all of the following:
76
76
 
77
77
  ## Setup Sequence
78
78
 
79
- Run steps in order. Each step reads the org state before it writes; if a precondition fails, the step surfaces the failure and stops without mutating the org. Every read and write below is a single `execute_api` call.
79
+ Run steps in order. Each step reads the org state before it writes; if a precondition fails, the step surfaces the failure and stops without mutating the org. Every read and write below is a single `dispatch` call.
80
80
 
81
81
  ### Step 0: Detect provisioning state and route
82
82
 
@@ -196,10 +196,10 @@ If `Metadata.enableLsdkMode` is already `true`, LDS is on — skip to Step 1.5.
196
196
  **1b. PATCH the full `Metadata` back with `enableLsdkMode: true`** — `PATCH /services/data/vXX.0/tooling/sobjects/FieldServiceSettings/{Id}`:
197
197
 
198
198
  ```json
199
- { "FullName": "FieldService", "Metadata": { "...all sibling keys from the GET...", "enableLsdkMode": true } }
199
+ { "Metadata": { "...all sibling keys from the GET...", "enableLsdkMode": true } }
200
200
  ```
201
201
 
202
- `FullName` is **required** on a Tooling `Metadata` PATCH — omitting it 400s with `FIELD_INTEGRITY_EXCEPTION` "Full name must be specified to update metadata" (verified against a live org). For the `FieldServiceSettings` singleton `FullName` is the literal `"FieldService"`; echo back the `FullName` returned by the 1a read. Send the **entire** `Metadata` object read in 1a with only `enableLsdkMode` flipped — a partial body nulls the omitted org prefs (`fieldServiceOrgPref`, `enableWorkOrders`, the search-field arrays, etc.). A 204 is success.
202
+ Send the **entire** `Metadata` object read in 1a with only `enableLsdkMode` flipped — a partial body nulls the omitted org prefs (`fieldServiceOrgPref`, `enableWorkOrders`, the search-field arrays, etc.). A 204 is success.
203
203
 
204
204
  **1c. Verify it actually flipped** — re-run the 1a Tooling read and confirm `Metadata.enableLsdkMode == true`. This guards the rare SDO/trial-org case where a write reports success but the flag stays false. If it did not flip, surface the Setup deeplink for the admin to toggle it by hand:
205
205
 
@@ -249,7 +249,7 @@ Most common SDO/trial-org symptom: PSLs all assigned, EinsteinSetup page exists,
249
249
  but the runtime entitlement was never turned on. 'Turn On Einstein' flips it.
250
250
  ```
251
251
 
252
- **1.5c. Re-probe after the admin completes the wizard.** Re-run the 1.5a `execute_api` call. Do not move on until it returns `promptRecords`.
252
+ **1.5c. Re-probe after the admin completes the wizard.** Re-run the 1.5a `dispatch` call. Do not move on until it returns `promptRecords`.
253
253
 
254
254
  ### Step 2: Enable the Voice to Record Edit org switch
255
255
 
@@ -268,13 +268,13 @@ V2RE's org-level switch lives on `FieldServiceMobileSettings`, a **regular sObje
268
268
 
269
269
  A 201 returns the new row Id (which already satisfies Step 2b — skip the PATCH).
270
270
 
271
- **2b. Flip `IsShowEditFullRecord` to true** on the existing row — `PATCH /services/data/vXX.0/sobjects/FieldServiceMobileSettings/{Id}`:
271
+ **2b. Flip `IsShowEditFullRecord` (and `IsDefault`) to true** on the existing row — `PATCH /services/data/vXX.0/sobjects/FieldServiceMobileSettings/{Id}`:
272
272
 
273
273
  ```json
274
- { "IsShowEditFullRecord": true }
274
+ { "IsShowEditFullRecord": true, "IsDefault": true }
275
275
  ```
276
276
 
277
- A 204 is success. **Do NOT include `IsDefault` in the PATCH body** — `IsDefault` is a create-only field and is *not updateable* on an existing row; sending it 400s with `INVALID_FIELD_FOR_INSERT_UPDATE` on `IsDefault` (verified against a live org). Set `IsDefault` only at create time via the 2a POST. If the existing row you're patching is not already the default (`IsDefault = false`) and you need it to be, you cannot flip it in place — the toggle then takes effect only on profiles explicitly mapped to this settings row via `MobileSettingsAssignment`; the simplest path for a pilot is to create the default row via 2a instead. Re-read the row (Step 0 diagnostic 4) to confirm `IsShowEditFullRecord` is `true`. The PATCH is idempotent: re-sending the same value returns 204 and changes nothing.
277
+ A 204 is success. Re-read the row (Step 0 diagnostic 4) to confirm both fields are `true`. Without `IsDefault = true`, the toggle takes effect only on profiles explicitly mapped to this settings row via `MobileSettingsAssignment` — `IsDefault = true` is the simplest path for a pilot. The PATCH is idempotent: re-sending the same values returns 204 and changes nothing.
278
278
 
279
279
  > **What the user sees on-device.** Per Salesforce help (`mfs_actions_order.xml`): once `IsShowEditFullRecord = true` and the user has Edit access to the object, **Edit Work Order**, **Edit Work Order Line Item**, and **Edit Service Appointment** appear in the Actions launcher on the Work Order Overview screen, after Quick Actions. The mobile app caches the settings — the technician must log out and back in for the new actions to appear.
280
280
 
@@ -372,7 +372,7 @@ Which forms do you want to enable Voice to Form on?
372
372
 
373
373
  There are two ways to flip it. Pick based on what's available in the runtime.
374
374
 
375
- **Path A (preferred — agent-native browser MCP drive).** Verified working end-to-end: V2F triggered correctly on the mobile app after this path enabled the flag on real forms. The browser MCP is part of the agent runtime (like `execute_api`), not a shell or an external tool the skill depends on.
375
+ **Path A (preferred — agent-native browser MCP drive).** Verified working end-to-end: V2F triggered correctly on the mobile app after this path enabled the flag on real forms. The browser MCP is part of the agent runtime (like `dispatch`), not a shell or an external tool the skill depends on.
376
376
 
377
377
  The sequence per form is exactly these clicks:
378
378
  1. Open Flow Builder on the form. Resolve the Flow Id for each selected form from the Step 5a list, then navigate the browser MCP to `<instanceUrl>/builder_platform_interaction/flowBuilder.app?flowId=<FLOW_ID>`. (The runtime supplies the authenticated session; the skill does not build `frontdoor.jsp` URLs or handle tokens.)
@@ -587,7 +587,7 @@ Run before declaring Voice to Form enabled in production:
587
587
 
588
588
  ## Conventions
589
589
 
590
- - **REST-native, no execution-environment dependency.** Every org read and write is a single `execute_api` REST call dispatched through the Codey runtime. The skill uses no `sf` CLI, no shell, no local Python or `jq`, no temp files, no metadata deploy, and no Apex. The one non-REST step (LLM Targetable) uses the agent-native browser MCP or a Setup deeplink — never a shell.
590
+ - **REST-native, no execution-environment dependency.** Every org read and write is a single `dispatch` REST call dispatched through the Codey runtime. The skill uses no `sf` CLI, no shell, no local Python or `jq`, no temp files, no metadata deploy, and no Apex. The one non-REST step (LLM Targetable) uses the agent-native browser MCP or a Setup deeplink — never a shell.
591
591
  - **Idempotent.** Re-running on an already-configured org applies zero changes. LDS/permset/PSL writes are safe to re-run (204/no-op or `DUPLICATE_VALUE` treated as success).
592
592
  - **Read API names back from the org.** PSL DeveloperName, the permset Id, the form API-name list, and the FSM Settings row Id are all read live, never hard-coded.
593
593
  - **Trust the runtime probe over Tooling settings probes.** `Ai4mSettings.enableEinsteinGPT` returns `<missing>` even on fully-enabled orgs. The only honest check is the live LLM call in Step 1.5a.