@salesforce/afv-skills 1.63.0 → 1.64.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 (137) hide show
  1. package/package.json +1 -1
  2. package/skills/agentforce-offline-experimentation-run/SKILL.md +253 -0
  3. package/skills/agentforce-offline-experimentation-run/scripts/build_report.py +796 -0
  4. package/skills/agentforce-offline-experimentation-run/scripts/resolve-token.sh +111 -0
  5. package/skills/agentforce-offline-experimentation-run/scripts/sfap_replay.py +1053 -0
  6. package/skills/automation-sandbox-post-copy-config-generate/SKILL.md +21 -11
  7. package/skills/automation-sandbox-post-copy-config-generate/assets/config_template.json +10 -0
  8. package/skills/automation-sandbox-post-copy-config-generate/assets/json_schema.json +33 -1
  9. package/skills/automation-sandbox-post-copy-config-generate/references/configuration_catalog.md +44 -1
  10. package/skills/automation-sandbox-post-copy-configure/SKILL.md +132 -124
  11. package/skills/automation-sandbox-post-copy-configure/references/flow_activation_path.md +151 -0
  12. package/skills/automation-sandbox-post-copy-configure/references/scheduled_apex_path.md +55 -9
  13. package/skills/consumer-goods-promotion-bo-api-deploy/SKILL.md +54 -107
  14. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/copy.json +1 -1
  15. package/skills/consumer-goods-promotion-bo-api-deploy/references/conventions-and-payload-rules.md +82 -5
  16. package/skills/consumer-goods-promotion-bo-api-deploy/references/generate-and-wire.md +35 -2
  17. package/skills/consumer-goods-promotion-bo-api-deploy/references/preflight-and-seed-queries.md +149 -0
  18. package/skills/consumer-goods-promotion-bo-api-deploy/references/smoke-and-verify.md +17 -1
  19. package/skills/dx-devops-conflict-resolve/SKILL.md +1 -5
  20. package/skills/dx-devops-pipeline-manage/SKILL.md +1 -5
  21. package/skills/dx-devops-project-manage/SKILL.md +1 -5
  22. package/skills/dx-devops-promote/SKILL.md +1 -5
  23. package/skills/dx-devops-request-status/SKILL.md +1 -5
  24. package/skills/dx-lifecycle-center/SKILL.md +120 -0
  25. package/skills/dx-lifecycle-center/examples/workflows.md +175 -0
  26. package/skills/dx-lifecycle-center/references/connect-api.md +123 -0
  27. package/skills/dx-lifecycle-center/references/connect-org.md +184 -0
  28. package/skills/dx-lifecycle-center/references/deploy.md +153 -0
  29. package/skills/dx-lifecycle-center/references/error-handling.md +21 -0
  30. package/skills/dx-lifecycle-center/references/hub-org.md +37 -0
  31. package/skills/dx-lifecycle-center/references/list-orgs.md +99 -0
  32. package/skills/dx-lifecycle-center/references/request-body.md +75 -0
  33. package/skills/dx-lifecycle-center/references/troubleshooting.md +31 -0
  34. package/skills/dx-lifecycle-center/scripts/poll-deploy-status.sh +200 -0
  35. package/skills/dx-lifecycle-center/scripts/resolve-environment.sh +120 -0
  36. package/skills/dx-org-devhub-configure/SKILL.md +1 -3
  37. package/skills/dx-org-shape-manage/SKILL.md +1 -5
  38. package/skills/dx-org-snapshot-manage/SKILL.md +1 -3
  39. package/skills/education-cloud-academic-calendar-generate/SKILL.md +1 -3
  40. package/skills/education-cloud-course-catalog-migrate/SKILL.md +1 -3
  41. package/skills/education-cloud-domain-configure/SKILL.md +1 -3
  42. package/skills/education-cloud-multi-campus-configure/SKILL.md +1 -3
  43. package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +1 -5
  44. package/skills/experience-ui-bundle-2gp-deploy/SKILL.md +1 -3
  45. package/skills/experience-ui-bundle-features-generate/SKILL.md +1 -5
  46. package/skills/experience-ui-bundle-mfa-configure/SKILL.md +1 -3
  47. package/skills/field-service-data-capture-migrate/SKILL.md +1 -3
  48. package/skills/insurance-brokerage-agency-billing-configure/SKILL.md +1 -3
  49. package/skills/marketing-message-test/SKILL.md +1 -3
  50. package/skills/nonprofit-fundraising-configure/SKILL.md +240 -0
  51. package/skills/nonprofit-fundraising-configure/references/gotchas.md +26 -0
  52. package/skills/nonprofit-fundraising-configure/references/mcp-invocation.md +678 -0
  53. package/skills/nonprofit-fundraising-configure/references/permission-targeting.md +35 -0
  54. package/skills/nonprofit-volunteer-management-model-get/SKILL.md +166 -0
  55. package/skills/nonprofit-volunteer-management-model-get/references/entities.md +315 -0
  56. package/skills/nonprofit-volunteer-management-model-get/references/relationships.md +175 -0
  57. package/skills/nonprofit-volunteer-management-model-get/references/themes.md +143 -0
  58. package/skills/nonprofit-volunteer-management-records-create/SKILL.md +121 -0
  59. package/skills/nonprofit-volunteer-management-records-create/references/field-guide.md +284 -0
  60. package/skills/nonprofit-volunteer-management-records-create/references/mcp-invocation.md +248 -0
  61. package/skills/nonprofit-volunteer-management-records-create/references/review-format.md +140 -0
  62. package/skills/nonprofit-volunteer-management-records-create/scripts/expand-series.py +632 -0
  63. package/skills/nonprofit-volunteer-management-records-create/scripts/render-review-table.py +419 -0
  64. package/skills/nonprofit-volunteer-management-records-create/scripts/tests/test_expand_series.py +690 -0
  65. package/skills/nonprofit-volunteer-management-records-create/scripts/tests/test_render_review_table.py +421 -0
  66. package/skills/nonprofit-volunteer-management-structure-generate/SKILL.md +119 -0
  67. package/skills/nonprofit-volunteer-management-structure-generate/references/configuration-decisions.md +159 -0
  68. package/skills/nonprofit-volunteer-management-structure-generate/references/discovery-interview.md +137 -0
  69. package/skills/nonprofit-volunteer-management-structure-generate/references/edge-cases.md +48 -0
  70. package/skills/nonprofit-volunteer-management-structure-generate/references/mcp-invocation.md +75 -0
  71. package/skills/nonprofit-volunteer-management-structure-generate/references/plan-output.md +141 -0
  72. package/skills/platform-custom-field-generate/SKILL.md +1 -0
  73. package/skills/platform-custom-field-generate/references/advanced-picklists.md +5 -5
  74. package/skills/platform-custom-metadata-type-generate/SKILL.md +3 -0
  75. package/skills/platform-custom-object-generate/SKILL.md +4 -0
  76. package/skills/platform-custom-setting-generate/SKILL.md +3 -0
  77. package/skills/platform-datamask-run/SKILL.md +1 -5
  78. package/skills/platform-permission-set-generate/SKILL.md +3 -0
  79. package/skills/platform-salesforce-connect-adapter-generate/SKILL.md +1 -3
  80. package/skills/platform-sandbox-configure/SKILL.md +1 -3
  81. package/skills/platform-value-set-generate/SKILL.md +3 -0
  82. package/skills/sales-call-scoring-configure/SKILL.md +1 -5
  83. package/skills/service-agentforce-channel-configure/SKILL.md +1 -3
  84. package/skills/service-agentforce-human-escalation-configure/SKILL.md +1 -3
  85. package/skills/service-catalog-template-coordinate/SKILL.md +1 -3
  86. package/skills/service-concierge-portal-generate/SKILL.md +1 -3
  87. package/skills/service-email-to-case-configure/SKILL.md +1 -5
  88. package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/SKILL.md +1 -3
  89. package/skills/service-itsm-agentic-setup-agentforce-coordinate/SKILL.md +1 -3
  90. package/skills/service-itsm-agentic-setup-agentforce-studio-configure/SKILL.md +1 -3
  91. package/skills/service-itsm-agentic-setup-agentforce-studio-validate/SKILL.md +1 -3
  92. package/skills/service-itsm-agentic-setup-cmdb-access-assign/SKILL.md +1 -3
  93. package/skills/service-itsm-agentic-setup-cmdb-bundle-deploy/SKILL.md +1 -5
  94. package/skills/service-itsm-agentic-setup-cmdb-configure/SKILL.md +1 -3
  95. package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +1 -3
  96. package/skills/service-itsm-agentic-setup-cmdb-discovery-configure/SKILL.md +1 -3
  97. package/skills/service-itsm-agentic-setup-employee-agent-configure/SKILL.md +1 -3
  98. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/SKILL.md +1 -3
  99. package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +1 -0
  100. package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/SKILL.md +1 -3
  101. package/skills/service-itsm-agentic-setup-uel-user-create/SKILL.md +1 -9
  102. package/skills/service-itsm-incident-mgmt-configure/SKILL.md +1 -5
  103. package/skills/service-itsm-incident-priority-configure/SKILL.md +1 -3
  104. package/skills/service-itsm-slack-itservice-configure/SKILL.md +1 -3
  105. package/skills/service-itsm-swarming-configure/SKILL.md +1 -3
  106. package/skills/service-itsm-teams-configure/SKILL.md +1 -3
  107. package/skills/service-itsm-teams-debug/SKILL.md +1 -3
  108. package/skills/service-itsm-teams-employee-agent-configure/SKILL.md +1 -3
  109. package/skills/service-itsm-teams-itdesk-configure/SKILL.md +1 -3
  110. package/skills/service-itsm-teams-itservice-configure/SKILL.md +1 -3
  111. package/skills/service-native-voice-recording-transcription-configure/SKILL.md +1 -3
  112. package/skills/service-omni-agent-users-create/SKILL.md +1 -3
  113. package/skills/service-omni-agent-work-sharing-configure/SKILL.md +1 -3
  114. package/skills/service-omni-attribute-routing-configure/SKILL.md +1 -3
  115. package/skills/service-omni-base-settings-configure/SKILL.md +1 -3
  116. package/skills/service-omni-channel-inventory-analyze/SKILL.md +1 -3
  117. package/skills/service-omni-channel-limits-analyze/SKILL.md +1 -3
  118. package/skills/service-omni-channel-setup-coordinate/SKILL.md +1 -3
  119. package/skills/service-omni-command-center-analyze/SKILL.md +1 -3
  120. package/skills/service-omni-command-center-configure/SKILL.md +1 -3
  121. package/skills/service-omni-permission-set-assign/SKILL.md +1 -3
  122. package/skills/service-omni-presence-status-deploy/SKILL.md +1 -3
  123. package/skills/service-omni-presence-user-config-deploy/SKILL.md +1 -3
  124. package/skills/service-omni-queue-deploy/SKILL.md +1 -3
  125. package/skills/service-omni-queue-members-assign/SKILL.md +1 -3
  126. package/skills/service-omni-queue-routing-config-deploy/SKILL.md +1 -3
  127. package/skills/service-omni-routing-flow-deploy/SKILL.md +1 -3
  128. package/skills/service-omni-service-channel-configure/SKILL.md +1 -3
  129. package/skills/service-omni-sidebar-configure/SKILL.md +1 -3
  130. package/skills/service-omni-skills-based-routing-configure/SKILL.md +1 -3
  131. package/skills/service-omni-supervisor-config-deploy/SKILL.md +1 -3
  132. package/skills/service-omni-supervisor-permset-assign/SKILL.md +1 -3
  133. package/skills/service-omni-supervisor-surface-deploy/SKILL.md +1 -3
  134. package/skills/service-omni-supervisor-users-create/SKILL.md +1 -3
  135. package/skills/service-omni-work-skill-routing-configure/SKILL.md +1 -3
  136. package/skills/field-service-setup-orchestrator-get/SKILL.md +0 -47
  137. package/skills/tableau-next-asset-create/README.md +0 -65
@@ -0,0 +1,678 @@
1
+ # MCP invocation reference — nonprofit-fundraising-configure
2
+
3
+ ## Contents
4
+
5
+ - Tool argument shape
6
+ - MCP client registration and External Client App setup
7
+ - Phase 0 caching rules
8
+ - Front-loading Phase 1's live checks
9
+ - Discovery-first approach for Fundraising-specific operations
10
+ - Identifying the current authenticated user
11
+ - Confirm-to-write checkpoint
12
+ - Person Accounts enablement (Layer 0) and Fundraising's dedicated enablement confirmation
13
+ - Status-recap table format
14
+ - Optional enhanced features (step 12)
15
+ - Error taxonomy
16
+
17
+ ## Tool argument shape (IMPORTANT)
18
+
19
+ `mcp__headless-360__dispatch` and `mcp__headless-360__dispatch_readonly` both take raw HTTP:
20
+
21
+ ```json
22
+ {
23
+ "url": "/services/data/vXX.0/...",
24
+ "method": "GET|POST|PATCH",
25
+ "body": { /* optional; required for POST/PATCH */ },
26
+ "queryParams": { /* required for SOQL — see note below */ }
27
+ }
28
+ ```
29
+
30
+ They do **not** take `{operation_id, arguments}` — that shape returns `INVALID_ARGUMENT: 'url'
31
+ and 'method' are required`. Every example below uses the `{url, method, body?, queryParams?}`
32
+ shape.
33
+
34
+ **`queryParams` is camelCase, not `query_params`** — `query_params` (snake_case) is silently
35
+ ignored (the request reaches Salesforce with no `q` at all, surfacing as a confusing
36
+ downstream `400 MALFORMED_QUERY: "A query string has to be specified"`, or as a gateway-side
37
+ `ROUTE_NOT_FOUND`/`404` depending on whether an inline querystring was also present). For a SOQL
38
+ call (`GET /services/data/vXX.0/query`), an inline querystring in `url` (`?q=...`) is **actively
39
+ rejected** — `400 INVALID_ARGUMENT: 'url' must not contain an inline query string — pass query
40
+ parameters via the 'queryParams' argument instead` — it is not merely "an alternative" to
41
+ `queryParams` as one might assume; `queryParams` is the only working mechanism for this server.
42
+ Always call SOQL as `{"url": "/services/data/vXX.0/query", "method": "GET", "queryParams": {"q":
43
+ "SELECT ..."}}`.
44
+
45
+ `discover` and `describe` are the indexing/schema tools:
46
+
47
+ - `mcp__headless-360__discover(query="<free text>")` — returns candidate indexed operations.
48
+ A miss does **not** mean the route is absent — standard Data API paths (`/query`,
49
+ `/sobjects/<Type>`) can be dispatched directly even when `discover` doesn't surface them.
50
+ - `mcp__headless-360__describe(id=<operation_id>)` — returns the input/output schema for a
51
+ discovered operation. Always call this before a `dispatch` write.
52
+
53
+ **Response envelope**: `dispatch*` returns `{ "status_code": 200, "body": <REST response> }`.
54
+ Read `body`. A create returns `body.id` and `body.success == true`; a query returns
55
+ `body.records[]`. Status codes: `200/201` success; `400` bad body (re-check schema via
56
+ `describe`); `401` the MCP session needs re-auth; `403` the executing user is missing a
57
+ permission; `404` the endpoint/sObject is not present on this org (surfaces separately as the
58
+ licensing/prerequisite checks in `SKILL.md` Phase 1); `500` a downstream dependency issue.
59
+
60
+ ---
61
+
62
+ ## MCP client registration and External Client App setup
63
+
64
+ Every org that dispatches through headless-360 needs a one-time **External Client App (ECA)**
65
+ registered in that org, plus the **headless-360 MCP Server** activated (Setup → MCP Server
66
+ Configuration). This is an org-admin, one-time task — not something this skill can do for
67
+ itself, since it is the very session credential the skill's own `dispatch*` calls depend on.
68
+
69
+ Required ECA configuration:
70
+
71
+ - Enable OAuth. OAuth Scopes: "Perform requests at any time (refresh_token, offline_access)"
72
+ and "Access Salesforce hosted MCP servers (mcp_api)".
73
+ - Flow Enablement: check "Enable Authorization Code and Credentials Flow"; leave "Require user
74
+ credentials in the POST body" unchecked (that sub-flow is for a different credential-embedding
75
+ variant, not the standard browser/PKCE flow).
76
+ - Security: leave PKCE and JWT-based access tokens for named users on (org-enforced defaults).
77
+ - After creation: set OAuth Policies (Permitted Users, IP Relaxation if the org enforces login
78
+ IP ranges), then Setup → MCP Servers → `headless-360` → Activate. ECA propagation can take up
79
+ to 30 minutes; MCP Server activation up to 2 minutes.
80
+
81
+ If a `discover`/`describe`/`dispatch*` call returns `401`, the MCP client is not authenticated to
82
+ the target org (session expired or the ECA/activation above is incomplete) — halt and surface the
83
+ raw error rather than retrying blindly.
84
+
85
+ ---
86
+
87
+ ## Phase 0 caching rules
88
+
89
+ `SKILL.md`'s Phase 0 (skip-if-already-known) is modeled on the identical section in
90
+ `service-itsm-incident-mgmt-configure/SKILL.md`. What qualifies as cache-eligible this session,
91
+ scoped to the current org (the `headless-360` session binds to one org via JWT):
92
+
93
+ **Cache-eligible** — a fact from a successful tool response this session, for the current org:
94
+ - `describe` schemas for any operation used below (`GiftDesignation`, `FundraisingConfig`,
95
+ Fundraising feature toggles, `PermissionSet`/`PermissionSetGroup`, the optional-features
96
+ operations) — stable within a session; reuse rather than re-`describe` the same operation twice.
97
+ - A prior `dispatch_readonly` read of `personAccountsEnabled`, `fundraisingLicensed`,
98
+ `orgPreferenceEnabled`, permission set/group resolution and `Status`, current feature-toggle
99
+ values, or the optional-features org preferences — reuse rather than re-querying, **unless**
100
+ a `dispatch` write elsewhere in this session could have changed that specific fact (this
101
+ skill's own writes, or a parent orchestrator's), in which case re-read.
102
+
103
+ **Never cache-eligible:**
104
+ - A user's verbal claim ("I already enabled it," "done") — only a live tool response is
105
+ authoritative. This is what Layer 0's pause-gate re-check and step 13's final verification
106
+ exist to enforce, and Phase 0 never overrides either: both always re-read live regardless of
107
+ what was cached earlier in the run, because their entire purpose is verifying an out-of-band
108
+ action (Setup UI, or a write whose response alone isn't proof) actually took effect.
109
+ - Anything from before a possible org-binding change. If the user hints at a different org, or
110
+ it's unclear which org an earlier fact came from, re-read rather than trust the cache.
111
+
112
+ When in doubt, re-check — a wrong skip on a live org write is worse than one duplicated read.
113
+
114
+ ---
115
+
116
+ ## Front-loading Phase 1's live checks (SKILL.md Workflow)
117
+
118
+ Each of steps 6–11 already needs a live read before deciding whether to write anything (Phase 0
119
+ caching above). Rather than resolving that read in step order — discover, describe, query,
120
+ maybe-write, repeat — resolve all six live checks as early as Phase 1 allows, before starting
121
+ Phase 3's writes: perm-set/group assignment coverage (6, 8), `orgPreferenceEnabled` (7), an
122
+ existing default `GiftDesignation` (9), `FundraisingConfig` field values (10), and the six
123
+ feature-toggle states (11).
124
+
125
+ "Batched" describes *when* these reads happen (grouped together, ahead of the writes), never *how
126
+ many* — this is still five to seven separate live queries, one per fact family above, each needing
127
+ its own `dispatch_readonly` (a single Tooling read of the toggle fields covers all six toggles in one
128
+ call, but perm-set coverage, `orgPreferenceEnabled`, `GiftDesignation`, and `FundraisingConfig` are
129
+ each a distinct object and need their own separate query). Collapsing this to one or two calls
130
+ total and calling it "batched" is under-verification, not the fast path this describes — it risks
131
+ concluding steps are complete when they were never actually checked.
132
+
133
+ This applies even when a request says "core setup is already done, skip it": the live batch is
134
+ still the minimum bar, not an optional extra — run every one of these reads regardless of what the
135
+ request claims, since a claim is never a substitute for a live query. Any step the batch confirms
136
+ is already satisfied moves straight to step 12's gate without its own discover/describe/confirm
137
+ cycle; any step the batch shows missing or wrong still gets the full step-by-step flow to fix it,
138
+ and every one of these facts must still be recorded in `state.json`'s per-step booleans even when
139
+ the request says to skip past them — "already done" shortens the path to step 12, it never
140
+ shortens what gets written to `state.json`.
141
+
142
+ ---
143
+
144
+ ## Discovery-first approach for Fundraising-specific operations
145
+
146
+ The exact operation IDs backing Nonprofit Cloud Fundraising can still be org- and
147
+ release-version-dependent, but the underlying object/field/type names are known and should be
148
+ used to target discovery rather than guessed at blind:
149
+
150
+ - `GiftDesignation` — standard sObject, `Name`/`IsActive`/`IsDefault`. Data API create/query.
151
+ - `FundraisingConfig` — settings type governing gift/recurring-donation-failure handling
152
+ (`installmentExtDayCount`, `lapsedUnpaidTrxnCount`, `failedTransactionCount`,
153
+ `shouldCreateRcrSchdTrxn`, `shouldClosePaidRcrCmt`). This is a
154
+ **Metadata API construct** in the underlying platform — confirm a Data/Tooling REST route
155
+ exists via `describe` before attempting a `dispatch` write; if none exists, that is a real
156
+ capability gap, not a routing miss.
157
+ - `enableFundraising` — the org-wide Fundraising enablement flag. It's owned by the
158
+ `FundraisingSettings` skill and set through its named `set-fundraising-org-preference` operation
159
+ (`describe` it first), unlike `FundraisingConfig` above. Because it's a one-way, irreversible, org-wide enable — unlike the six feature toggles,
160
+ which are independently reversible — it gets its own dedicated warning and confirmation
161
+ (`SKILL.md` Phase 2 step 5) before Phase 3 step 7 dispatches it, on top of the ordinary
162
+ confirm-to-write checkpoint. Read its state via the `FundraisingSettings`
163
+ skill's `get-settings-view-model` (`orgPreferenceEnabled`) early, in Phase 1 — do this before, not after, resolving permission sets
164
+ — since `orgPreferenceEnabled = false` also means `GiftDesignation` won't resolve as a queryable
165
+ sObject and `save-fundraising-settings` will refuse to write.
166
+ - `PermissionSet` — Fundraising's name has been observed as both `force__FundraisingAccess` and
167
+ unprefixed `FundraisingAccess` across orgs; query for both candidates.
168
+ - `PermissionSetGroup` — `Fundraising_Admin`/`Fundraising_User` (`DeveloperName`); check
169
+ `Status = 'Updated'` (not `'Updating'`) before assigning.
170
+
171
+ ### FundraisingConfig field defaults
172
+
173
+ Fields: `installmentExtDayCount`, `lapsedUnpaidTrxnCount`, `failedTransactionCount`,
174
+ `shouldCreateRcrSchdTrxn`, `shouldClosePaidRcrCmt`. If the user hasn't stated a preference,
175
+ reasonable operational defaults are `installmentExtDayCount=1`, `lapsedUnpaidTrxnCount=3`,
176
+ `failedTransactionCount=1`, `shouldCreateRcrSchdTrxn=true`, `shouldClosePaidRcrCmt=true`.
177
+
178
+ `donorMatchingMethod` is deliberately **not** written: a new org defaults it to `No_Matching`, and
179
+ setting `Duplicate_Management_Rules` would also require the inactive Person Account matching and
180
+ duplicate rules to be activated manually in Setup. Leave it at the platform default unless the
181
+ admin explicitly asks for it.
182
+
183
+ `DonorExternalIdField` is a separate `FundraisingConfig` field (the donor-lookup External ID) and
184
+ is reachable via a plain Data API update — no Metadata-API caveat here. Its Setup UI control shows
185
+ disabled/greyed on many orgs; that is **not** a Fundraising-sequencing gate, it is conditional on
186
+ the org having a field marked as an external ID on the donor object. Resolve it deterministically —
187
+ `IsExternalId` is NOT a queryable column on `FieldDefinition` or `EntityParticle` (400
188
+ `INVALID_FIELD` on both, regardless of org). The only correct source is a full object describe —
189
+ `dispatch_readonly` `GET /services/data/vXX.0/sobjects/<donor object>/describe`, then scan its
190
+ `fields[]` client-side for an entry with `externalId: true`:
191
+
192
+ ```text
193
+ fields[] entries look like: { "name": "...", "externalId": true|false, "idLookup": ..., ... }
194
+ ```
195
+
196
+ If a match exists, set `DonorExternalIdField` to that field's `name`; if none exists, fall back to
197
+ the donor name field. No admin prompt is needed either way — this is fully determined by what the
198
+ org's schema already has. The describe response is large (100K+ characters for a standard object
199
+ like `Contact`) — that's expected for this call, not a sign something's wrong.
200
+
201
+ ### Fundraising feature toggles
202
+
203
+ None of these toggles are written through the `IndustriesSettings` Metadata API — that surface is
204
+ not available on every org, so this skill never uses it for a write. Of the six toggles, two route
205
+ through separate named controllers, and the remaining four route through a generic Setup
206
+ org-preference operation. See the last bullet below for why a seventh candidate toggle was dropped
207
+ from this skill. Re-`describe`/re-test on any new org before assuming this generalizes.
208
+
209
+ There is no `enableEnhancedCommitmentProcessor` toggle to dispatch: NextGen Commitment Processing
210
+ (org preference `FrEnhancedCmtPrscrEnabled`) is force-enabled as a side effect of `FundraisingSettings`'
211
+ Layer-0 `set-fundraising-org-preference` call (which
212
+ co-enables it alongside the base Fundraising and Gift Entry Grid preferences, unconditionally, no
213
+ branch). `FundraisingSettings.save-fundraising-settings`'s `isNextGenCmtPrcsParallel` field is a
214
+ separate, unrelated parallel-execution tuning knob for an already-enabled feature — it does not
215
+ enable or disable NextGen Commitment Processing, so don't dispatch it under the assumption that it
216
+ does.
217
+
218
+ - **Not `IndustriesSettings` at all — use the named controller/operation directly**:
219
+ `enableGiftEntryGrid` → the `FundraisingGiftEntrySettings` skill's grid-preference toggle;
220
+ `enableSourceCodeGeneration` → the `FundraisingSourceCodeGen` skill's `set-source-code-generation-enabled`.
221
+ `describe` each skill and follow it rather than restating its route or body here.
222
+ Never write these two as `IndustriesSettings` fields — the field names exist in the metadata
223
+ schema but the real write path is elsewhere.
224
+ - **Generic Setup org-preference operation**: `enableGiftPlanning` → `GiftPlanningEnabled`;
225
+ `enableGiftAgreement` → `GiftAgreementEnabled`; `enablePhilResearchAgent` →
226
+ `PhilResearchAgentEnabled`; `enableInteractionSummaryPref` → `InteractionSummaryPref`. Write via
227
+ `platform.setup.setup-metadata.setOrgPreference` (`PATCH
228
+ /headless/invoke/platform/setup/setup-metadata/set-org-preference`, body `{"orgPreferences":
229
+ {"<Name>": <bool>}}`). Do **not** use this operation's read side (`isOrgPreferenceEnabled`) for
230
+ verification: it takes a list-valued parameter that the dispatch path cannot carry, so
231
+ the call fails `400 REQUEST_ERROR "Invalid request"` however it is encoded — not a usage mistake. Verify instead with the best-effort Tooling read described under "Verifying a toggle" below.
232
+
233
+ `GiftPlanningEnabled`, `GiftAgreementEnabled`, `PhilResearchAgentEnabled` — enable/disable both
234
+ verified. `InteractionSummaryPref` — enable works; **disabling this one field currently fails**
235
+ (`500`), so it's not a routing issue — don't rely on disable for this field without
236
+ re-verifying. Its access-check mismatch
237
+ (a cross-industry entitlement rather than a Fundraising-owned check) does not block
238
+ enable on a Fundraising-provisioned org — cross-industry access is commonly co-provisioned, so
239
+ don't assume the mismatch blocks this toggle.
240
+ - **Not routed anywhere — dropped from this skill**: `enableActionPlanTaskComment` has no entry in
241
+ the generic operation's access map, and there is no safe alternative write path. Out of scope for
242
+ this skill.
243
+
244
+ All six toggles ride `SKILL.md` step 5's single confirm-to-write checkpoint — never add a
245
+ separate confirmation per toggle, including for `enablePhilResearchAgent`.
246
+
247
+ **Verifying a toggle**: `IndustriesSettings` may be readable via the Tooling API, but it is not
248
+ present on every org, so treat this read as best-effort. `dispatch_readonly` a Tooling query:
249
+ `{"url": "/services/data/vXX.0/tooling/query", "method": "GET", "queryParams": {"q": "SELECT
250
+ <ToolingFieldName> FROM IndustriesSettings"}}`. The Tooling field name is **not** the write-side
251
+ preference name — the mapping is `enable<X>Pref` → `Is<X>PrefEnabled`, e.g.
252
+ `enableInteractionSummaryPref` → `IsInteractionSummaryPrefEnabled`; fields newer than the API
253
+ version in the URL return `400 INVALID_FIELD`, so query a recent version (`v68.0`+) before
254
+ concluding a field is missing. If the object itself is unavailable on the org (query fails with
255
+ `INVALID_TYPE`, `404`, or a persistent `INVALID_FIELD` at a recent version), **do not fall back to
256
+ any metadata write or deploy** — report the toggle as "written, unverified" and tell the admin to
257
+ confirm it in Setup. Never trust a write response alone when a read-back is available.
258
+
259
+ Discovery procedure:
260
+
261
+ 1. `discover` with free-text queries targeting the above (e.g. `"Fundraising settings"`,
262
+ `"Gift Designation object"`, `"Nonprofit Cloud permission set group"`).
263
+ 2. `describe` every candidate operation before using it, to get the authoritative field list and
264
+ confirm it's actually dispatchable via REST (not Metadata-API-only).
265
+ 3. When `discover` returns nothing for a standard Data API shape (`PermissionSet`,
266
+ `PermissionSetGroup`, `RecordType`, `GiftDesignation` are core/standard sObjects), probe the
267
+ documented path directly with `dispatch_readonly` rather than treating the `discover` miss as
268
+ a hard failure.
269
+ 4. If a direct probe also 404s, or `describe` shows no REST-dispatchable route for a
270
+ Metadata-API-only construct (`FundraisingConfig`), that is a real
271
+ signal — report it as a missing prerequisite or capability gap rather than guessing at an
272
+ alternative path.
273
+
274
+ ### Enabling Fundraising (`set-fundraising-org-preference`)
275
+
276
+ `enableFundraising` is not one of the six toggles above — it's the master org-wide switch, and
277
+ unlike those six, it's irreversible rather than independently reversible. It rides its own
278
+ named headless-360 operation, `set-fundraising-org-preference`,
279
+ which turns on the org preference and writes the default `FundraisingConfig` row in the same
280
+ transaction.
281
+
282
+ - Dispatch: `describe` the `FundraisingSettings` skill first, same as any other write, and follow its
283
+ `set-fundraising-org-preference` step rather than restating its route or body here.
284
+ - Verify via that skill's `get-settings-view-model` read → `orgPreferenceEnabled = true` (the same
285
+ read as Phase 1 step 4).
286
+ - Because this write is irreversible and org-wide (unlike the reversible feature toggles), `SKILL.md` Phase 2
287
+ step 5 requires its own dedicated warning + `AskUserQuestion` confirmation before Phase 3 step 7
288
+ dispatches it — in addition to, not replacing, the plan-wide confirm-to-write checkpoint that
289
+ covers every other write in the plan.
290
+ - If a live `dispatch`/`describe` attempt on this exact org shows no dispatchable route for
291
+ `set-fundraising-org-preference` at all, treat that as a blocking capability gap and stop — there is no
292
+ supported alternative write for this field, so do **not** fall back to a Metadata API write.
293
+ - `navigate-fundraising-turn-on` remains available as an optional, human-driven alternative for an
294
+ admin who'd rather perform this specific irreversible action themselves through Setup.
295
+
296
+ ---
297
+
298
+ ## Identifying the current authenticated user
299
+
300
+ `PermissionSetAssignment` writes must target a human user, but this MCP server exposes no
301
+ dedicated "who am I" endpoint, and the obvious Connect API route
302
+ (`GET /services/data/vXX.0/connect/user-profiles/me`, and `/chatter/users/me`) can be disabled on
303
+ the org entirely (`403 FUNCTIONALITY_NOT_ENABLED`) — seen live. `GET /services/oauth2/userinfo`
304
+ is also not proxied by this server (`ROUTE_NOT_FOUND`).
305
+
306
+ Fallback heuristic when both of those fail:
307
+
308
+ 1. Query active users: `SELECT Id, Username, Name, UserType, IsActive, ProfileId FROM User WHERE
309
+ IsActive = true AND UserType = 'Standard' ORDER BY LastLoginDate DESC NULLS LAST`.
310
+ 2. `UserType = 'Standard'` alone is **not sufficient** — built-in integration/bot accounts (seen
311
+ live: "SalesforceIQ Integration", "Insights Integration", "Bot User", "DigitalAgent.*") also
312
+ carry `UserType = 'Standard'`. Exclude names matching those patterns.
313
+ 3. Cross-check the remaining candidates' `ProfileId` against `Profile.Name` — prefer one that
314
+ resolves to `'System Administrator'`.
315
+ 4. Prefer the most recent `LastLoginDate` among what's left.
316
+
317
+ This is an inference, not a guarantee — state that explicitly when reporting which user was used
318
+ as the assignee, so a human reviewing the run can correct it if wrong.
319
+
320
+ ---
321
+
322
+ ## Confirm-to-write checkpoint (REQUIRED)
323
+
324
+ Before any `dispatch` write that assigns a permission set/group, creates the default Gift
325
+ Designation record, enables Fundraising, or flips a feature toggle, present the full plan via
326
+ `AskUserQuestion` and wait for explicit confirmation. This mirrors the confirm-to-write pattern in
327
+ `service-itsm-incident-mgmt-configure` and `service-itsm-agentic-setup-uel-user-create` — the
328
+ distinction from the pause-and-resume gate below is that these actions are ones the *agent itself*
329
+ can perform after a "yes." Fundraising enablement rides this checkpoint too, but — because it's
330
+ irreversible and org-wide, unlike every other write here — it also gets its own dedicated warning
331
+ and confirmation on top of it; see the next section.
332
+
333
+ ## Person Accounts enablement (Layer 0) and Fundraising's dedicated enablement confirmation
334
+
335
+ A real headless enablement chain exists: `discover(query="enable Person Accounts")` surfaces
336
+ `hr-service-person-account-setup`, and `describe` on it returns a full, `implemented`-status chain
337
+ including `accept-terms-and-conditions` and `enable-person-accounts`. This was Setup-UI-only
338
+ historically; it no longer is. But that SOR is **HR-Service's own workflow**, not
339
+ Fundraising's, so this skill must never delegate to it or run its step list — call exactly the four operations
340
+ below, directly by path, and nothing else. This is an allowlist, not a skip-list: whatever other
341
+ steps that SOR contains today, adds, or renames later, this skill is unaffected as long as these
342
+ four paths keep working, because it never calls the SOR by id in the first place.
343
+
344
+ 1. `GET /headless/invoke/platform/person-account-settings/check-person-account-readiness` — returns
345
+ `personAccountsEnabled`, `termsConditionsAccepted`, `accountRecordTypeCreated`, `profilePermsSet`,
346
+ `orgWideSharingSet`, `allStepsComplete`. If `personAccountsEnabled` is already `true`, skip the
347
+ rest of this chain. `accountRecordTypeCreated` and the profile-visibility gate are already
348
+ satisfied by this skill's own Business Account record type and profile-visibility sub-checks
349
+ below — run those first if either gate is still false. If `profilePermsSet`/`orgWideSharingSet`
350
+ are false for a reason not covered by those sub-checks, fall back to the manual Setup UI gate for
351
+ just the unmet gate rather than blocking the whole chain on it.
352
+ 2. `PATCH /headless/invoke/platform/person-account-settings/accept-terms-and-conditions` once
353
+ `accountRecordTypeCreated` is true. Re-read step 1 and assert `termsConditionsAccepted = true`
354
+ before continuing — never trust the `PATCH` response alone.
355
+ 3. **Explicit confirmation, then the irreversible write.** `enable-person-accounts` is documented
356
+ IRREVERSIBLE by the operation itself ("Do NOT call without explicit user confirmation") — gate it
357
+ exactly like Fundraising's own dedicated enablement confirmation below: warn that it's irreversible
358
+ and org-wide, get an explicit `AskUserQuestion` confirmation, then `PATCH
359
+ /headless/invoke/platform/person-account-settings/enable-person-accounts`. On decline, stop, zero
360
+ further writes, `STOPPED_PERSON_ACCOUNTS_MISSING`.
361
+ 4. Re-verify via step 1's `GET` again (`personAccountsEnabled = true`) and the existing
362
+ `FieldDefinition` check Layer 0 already runs (`IsPersonAccount` on `Account`, `totalSize > 0`) —
363
+ never trust the `PATCH` response alone. Post-enable artifacts can materialize asynchronously; if
364
+ the re-check doesn't show it immediately, wait a couple of seconds and retry once before treating
365
+ it as a real failure.
366
+
367
+ **Why an allowlist, not a skip-list**: as of this writing, the discovered SOR's other steps create
368
+ an `Employee` record type, assign it to profiles, and enable `ReportsToOnPersonAccount` —
369
+ HR-Service's data model, not Fundraising's. That's context for *why* this skill only calls the four
370
+ paths above, not a maintained list to keep excluding — don't add "and also skip step N" here when
371
+ the SOR changes; the four operations above are the entire contract regardless.
372
+
373
+ If `discover` ever stops returning this operation, or `describe` no longer shows it as
374
+ `implemented`, fall back to the old live pause-and-resume gate: present the exact manual Setup
375
+ steps, ask via `AskUserQuestion` whether the admin has completed them, and re-run the readiness
376
+ check before trusting it either way — a "yes, I did it" is a claim, not a fact.
377
+
378
+ Fundraising enablement (Phase 1 step 4 / Phase 2 step 5) uses the same confirm-then-dispatch
379
+ pattern — a single named `PATCH` operation, `set-fundraising-org-preference` (see "Enabling
380
+ Fundraising" above), gated the same way as `enable-person-accounts` above.
381
+
382
+ **Person Accounts (Phase 2 step 5)** — Layer 0 only detects; ask for confirmation as part of the
383
+ plan, *before any write in this chain*, including the Business Account record type check/create
384
+ below: it's reversible on its own, but a normal Fundraising request must not touch org metadata
385
+ without consent when Person Accounts isn't enabled yet. This single confirmation also satisfies
386
+ step 3's gate above — don't ask twice. Phase 3 step 6a performs the writes only after it. The prompt:
387
+ *"Person Accounts isn't enabled on this org. Nonprofit Cloud Fundraising models donors as Person
388
+ Accounts, so none of the setup below can proceed without it. I'll create a Business Account record
389
+ type (reversible) and then enable Person Accounts (irreversible, org-wide) via the same headless
390
+ operations Setup uses. Proceed?"* Options: *"Yes — proceed"* / *"Stop here"*. On "Yes," check/create
391
+ the record type (see "Business Account record type" below), then run the chain above; re-check
392
+ readiness before continuing either way.
393
+
394
+ **Fundraising org preference (Phase 2 step 5)** — Warn, don't redirect: *"Enabling Fundraising
395
+ permanently turns on all Fundraising objects and functionality for this org and cannot be
396
+ reversed. I'll dispatch the Fundraising enablement operation — do you want to proceed?"* Options:
397
+ *"Yes — enable it"* / *"Stop"*. On "Yes," Phase 3 step 7 dispatches
398
+ `set-fundraising-org-preference` and re-verifies via `get-settings-view-model` →
399
+ `orgPreferenceEnabled` before treating it as done — never trust the dispatch response alone.
400
+ "Stop" ends the run with zero writes — no permission set/group assignment or any other step —
401
+ in `STOPPED_ENABLEMENT_NOT_CONFIRMED`.
402
+
403
+ For Person Accounts: if a re-check still fails after the confirmed write, say so plainly (propagation
404
+ delay, or the write itself errored) and re-run the chain from step 1 rather than assuming success —
405
+ never trust a "done" claim or a `PATCH` response alone.
406
+
407
+ For Fundraising: if the re-check after dispatching `set-fundraising-org-preference` still shows
408
+ `orgPreferenceEnabled = false`, treat it as a write issue, not a Setup-UI claim problem — check
409
+ the `dispatch` response for errors, and retry once before reporting `STOPPED_OTHER` with the error
410
+ as `stopReason`.
411
+
412
+ ### Person Accounts record-type profile visibility (a Layer 0 sub-check, distinct from enablement)
413
+
414
+ Layer 0's `FieldDefinition` check only confirms Person Accounts is enabled org-wide (the
415
+ `IsPersonAccount` field exists on `Account`) — it does **not** confirm any non-admin profile can
416
+ actually select or default to the Person Account record type. These are two different layers:
417
+ Person Accounts being enabled vs. a **profile** having `recordTypeVisibilities` for the record type.
418
+ Person Accounts being enabled (`personAccountsEnabled: true`, `Account.Person Account` record type
419
+ active) does not imply any profile has visibility for it. System Administrator can still select
420
+ every record type (implicit access), but neither profile necessarily has Person Account as its
421
+ default, and **Standard User** may not be able to select it until this is set. A profile retrieve
422
+ cannot tell you which — see the verify bullet below for how to read the real state.
423
+
424
+ Unlike Person Accounts enablement itself, this is **not** irreversible or Setup-UI-only, so it
425
+ doesn't need the pause-and-resume treatment — it's an ordinary declarative Metadata API deploy,
426
+ same class as the other Profile/PermissionSet writes this skill already performs.
427
+
428
+ - **Target state, for both `Standard User` and `System Administrator`**: both
429
+ `Account.Business_Account` and `PersonAccount.PersonAccount` are in the profile's selected record
430
+ types (`visible: true`), and **Person Account is the default** (`PersonAccount.PersonAccount` gets
431
+ `default: true` and `personAccountDefault: true`; `Account.Business_Account` gets
432
+ `default: false`). Setting the default explicitly also covers System Administrator, whose
433
+ implicit access to every record type does not make Person Account its default.
434
+ - **H360 first, per policy**: `discover` for this returns no dedicated SOR (best hits — "managing-
435
+ profiles", "UserManagementSettings" — are off-target). The closest real hit is a *step inside* an
436
+ unrelated workflow SOR, `hr-service-person-account-setup`'s `assign-record-types-to-profiles`
437
+ step: `PUT /headless/metadata` with `type: "Profile"`, `fullName` = the profile's developer name
438
+ (`Admin` for System Administrator, `Standard` for Standard User), and an `xmlRep` containing only
439
+ the `<recordTypeVisibilities>` fragments being set (one per record type) — **PUT, not POST, and a
440
+ minimal fragment only, never a full-Profile round-trip** (the SOR's own guidance; matches this
441
+ skill's existing "omit optional fields, let the platform default them" rule). Confirms the
442
+ mechanism (Metadata API `Profile.recordTypeVisibilities`), not a dispatchable op of its own — it's
443
+ HR-Service's Business Account/Employee record types, not Fundraising's. Adapt the fragments to
444
+ `Account.Business_Account` and `PersonAccount.PersonAccount` instead.
445
+ - **Scope is the active human users' profiles** — reuse step 6's human-user set
446
+ (`IsActive=true AND UserType='Standard'`) and its `Profile.Name` classification (see
447
+ `references/permission-targeting.md`), which resolves to `System Administrator` (Admin) and
448
+ `Standard User` (Standard). Apply the target state to both. Any other profile an active human user
449
+ holds (custom/unclassified) is left alone and reported as manual.
450
+ - **Fallback: Metadata API deploy.** `/headless/metadata` is not available on every org (it returns
451
+ `404 NOT_FOUND`, even for types that work elsewhere). When the headless `PUT` is rejected or 404s,
452
+ deploy the same minimal `Profile` fragment through the Metadata API (`sf project deploy start`
453
+ with a project holding only the two profile files; a `--dry-run` validates first). Each profile
454
+ file contains only:
455
+ ```xml
456
+ <Profile xmlns="http://soap.sforce.com/2006/04/metadata">
457
+ <recordTypeVisibilities>
458
+ <default>false</default>
459
+ <recordType>Account.Business_Account</recordType>
460
+ <visible>true</visible>
461
+ </recordTypeVisibilities>
462
+ <recordTypeVisibilities>
463
+ <default>true</default>
464
+ <personAccountDefault>true</personAccountDefault>
465
+ <recordType>PersonAccount.PersonAccount</recordType>
466
+ <visible>true</visible>
467
+ </recordTypeVisibilities>
468
+ </Profile>
469
+ ```
470
+ Profiles merge on deploy, so the fragment does not disturb other profile settings. Only if both
471
+ routes fail, tell the admin to add both record types under each profile's Record Type Settings in
472
+ Setup, set Person Account as the default, and report the sub-check as manual.
473
+ - **Verify, don't assume broken**: a Metadata API retrieve of `Profile:Admin`/`Profile:Standard`
474
+ **alone returns no `recordTypeVisibilities`** — the entries appear only when the record types are
475
+ in the same retrieve. Retrieve `Profile:Admin`, `Profile:Standard`,
476
+ `RecordType:Account.Business_Account` and `RecordType:PersonAccount.PersonAccount` together (note
477
+ the `PersonAccount.` prefix for the person record type), then confirm both entries are present
478
+ with `visible=true` and that `PersonAccount.PersonAccount` is the default, before reporting this
479
+ sub-check as resolved. Reading a profile without the record types and concluding "not set" is a
480
+ false negative.
481
+
482
+ ### Business Account record type (a Layer 0 sub-check, distinct from enablement)
483
+
484
+ Salesforce enforces creating a Business Account record type as a **hard precondition** for
485
+ enabling Person Accounts at all — it's one of the wizard's own readiness gates
486
+ (`accountRecordTypeCreated`), not an optional nice-to-have. Salesforce does not auto-provision it —
487
+ an org may already have it (`Business_Account`, active) only because an admin created it manually.
488
+ Today this sub-step is invisible, bundled inside the generic Layer 0 manual pause-and-resume gate above
489
+ ("Go to Setup → Person Accounts and complete the steps...") — an admin has no way to tell from
490
+ that prompt that record-type creation is one of the things being asked of them.
491
+
492
+ Unlike Person Accounts enablement itself, this specific write is **not** irreversible or
493
+ Setup-UI-only — it's an ordinary, reversible Metadata API write, the same class of write this
494
+ skill already automates elsewhere. That makes it safe to pull out of the manual bundle and
495
+ automate — but only under the same upfront confirmation gate as the (now also automatable)
496
+ T&C-acceptance and enable-Person-Accounts steps, never ahead of or outside it: see "Person
497
+ Accounts enablement (Layer 0)" above.
498
+
499
+ - **H360 first, per policy**: `discover` for "create a Business Account record type before
500
+ enabling Person Accounts" returns no dedicated standalone SOR (best hit, ~0.66, is the *parent*
501
+ workflow SOR below, not an isolated operation); a second `discover` with `resultType: "endpoint"`
502
+ confirms the same — no closer match. The closest real hit is again a *step inside* an unrelated
503
+ workflow SOR, `hr-service-person-account-setup`'s `create-business-account-record-type` step —
504
+ same pattern as the profile-visibility sub-check above: it's HR-Service's flow, not
505
+ Fundraising's, so treat it as a lead on the mechanism, not a dispatchable op of its own.
506
+ - **That SOR's documented mechanism is wrong**: its step calls `POST /headless/metadata` with
507
+ `type: "RecordType"` (a `PUT` with `type: "CustomObject"` wrapping a nested `<recordTypes>` block
508
+ behaves the same way) — both are rejected with `400 UNSUPPORTED_OPERATION` /
509
+ `"MetadataCrud does not support CREATE on type: RecordType"`, a flat routing rejection, not a
510
+ `DUPLICATE_VALUE`. Don't trust an `implemented`-status SOR step's mechanism as proven just because
511
+ another skill's workflow lists it — verify it before reusing it, same as any carried-over claim.
512
+ - **Working mechanism**: a plain sObject REST create — `POST /services/data/v69.0/sobjects/RecordType`
513
+ with body `{"Name": "Business Account", "DeveloperName": "Business_Account", "SobjectType":
514
+ "Account"}` — no Metadata API deploy, no xmlRep. This matches the `CollaborationGroupRecordTypes`
515
+ SOR's documented pattern for a different object exactly ("Uses the standard RecordType sObject
516
+ \[…\]. Required fields on create: Name, DeveloperName, SobjectType"), which is what pointed at the
517
+ right mechanism, and is round-tripped end to end by the companion **Household** record type create
518
+ below (`201`, re-queried and present).
519
+ - **Sequencing**: no dependency on anything HR-Service-specific — this is a plain, standalone
520
+ sObject create, clean to run ahead of the Person Accounts manual gate.
521
+ - **Design**: query `SELECT Id, DeveloperName, IsActive FROM RecordType WHERE SObjectType =
522
+ 'Account' AND DeveloperName = 'Business_Account'` first; skip if an active row exists; otherwise
523
+ `dispatch` the sObject create above; re-query to confirm before continuing to the (now narrower)
524
+ manual gate for the remaining, genuinely irreversible steps.
525
+
526
+ ### Household record type (optional, standalone — not a Layer 0 precondition)
527
+
528
+ Unlike Business Account, a Household record type on Account is **not** required by anything —
529
+ Salesforce doesn't gate Person Accounts or any other enablement on it. It's an org-owner
530
+ convenience some admins create alongside Business Account so household-style donors have a
531
+ dedicated record type too, not a requirement.
532
+
533
+ - **H360 first, per policy**: no dedicated SOR exists. `discover` for "create Household record
534
+ type on Account for Nonprofit Cloud" and "configure household account record type" both surface
535
+ only off-target or unrelated hits — FSC's `industries-fsc-householding-connect-api` (a
536
+ *different*, license-gated Household **object** for wealth-management householding, not an
537
+ Account record type) and the same `hr-service-person-account-setup` lead as above — no existing
538
+ precedent to copy, confirming this really is a gap, not a missed lookup.
539
+ - **Mechanism**: same plain sObject create as Business Account — `POST
540
+ /services/data/v69.0/sobjects/RecordType` with `{"Name": "Household", "DeveloperName":
541
+ "Household", "SobjectType": "Account"}`. Returns `201`, `success: true`; re-query to confirm
542
+ present and active (`DeveloperName='Household'`, `IsActive=true`).
543
+ - **Design**: query `SELECT Id, DeveloperName, IsActive FROM RecordType WHERE SObjectType =
544
+ 'Account' AND DeveloperName = 'Household'` first; skip if an active row exists; otherwise
545
+ `dispatch` the create above; re-query to confirm. Offer this as its own optional step (not folded
546
+ into Layer 0, since nothing gates on it).
547
+
548
+ ---
549
+
550
+ ## Status-recap table format
551
+
552
+ Both the core-setup recap immediately before step 12's combined ask, and step 14's final rollup,
553
+ must be a compact **Item | Status** markdown table — never a run-on prose paragraph. A table lets
554
+ the admin see at a glance exactly what's configured vs. what's still optional vs. what needs their
555
+ own manual action, which a sentence buries. Use plain, specific status values (`Enabled`,
556
+ `Assigned (N users)`, `Created`, `Skipped — <reason>`, `Failed — <reason>`, `Manual action required
557
+ — see below`) rather than a generic "done"/"not done".
558
+
559
+ Pre-step-12 recap (core setup, steps 6–11) — one row per item, e.g.:
560
+
561
+ | Item | Status |
562
+ |------|--------|
563
+ | Fundraising license | Confirmed |
564
+ | `FundraisingAccess` (org-wide) | Assigned (5 users) |
565
+ | Fundraising org preference | Enabled |
566
+ | Permission set groups (`Fundraising_Admin`/`Fundraising_User`) | Assigned by role |
567
+ | Default Gift Designation | Created ("General Fund") |
568
+ | Basic gift/recurring-donation settings | Configured |
569
+ | Feature toggles (6/6) | Enabled |
570
+
571
+ Step 14's final rollup extends the same table with whichever optional-feature rows from step 12
572
+ were actually attempted (see "Optional enhanced features" below for what belongs in each row —
573
+ e.g. Record Alerts shows category creation and org-preference guidance as separate rows, since only the first is verifiable), plus a closing `outcome`/`stopReason` line. Never collapse a
574
+ partially-completed feature into a single "done" row — if Life Events' license was assigned but
575
+ the Business Milestones related list still needs the admin's own manual Setup action, say so as
576
+ two distinct rows, not one that implies full completion.
577
+
578
+ ## Optional enhanced features (step 12)
579
+
580
+ Offered once, combined, via a single `AskUserQuestion` after core setup (steps 6–11) completes —
581
+ never one prompt per feature. Refer to each feature by its product name in the prompt (e.g.
582
+ "Timeline"), never by an underlying metadata field name. Per-feature mechanism, headless-360 only
583
+ (no Metadata API write or CLI deploy for any of them):
584
+
585
+ - **Interest Tags** — the org preference is owned by the Interest Tagging Setup skill, not the
586
+ Metadata API. `describe` id `InterestTaggingSettings` and follow its steps for the check, the
587
+ write and the verification; do not restate or improvise them here. If that skill's access check
588
+ or write fails (the org or user lacks the Interest Tagging feature or permission, or the type
589
+ is unavailable), tell the admin to turn on Interest Tagging on the Setup **Interest Tagging
590
+ Settings** page (`/lightning/setup/InterestTaggingSettings/home`) and never fall back to the
591
+ Metadata API or the CLI. Once it is on, seed categories via a plain Data API create against
592
+ `TagCategory`. The `InterestTag` records themselves are Setup-UI-only — there is no Data API
593
+ create route for them; don't attempt one.
594
+ - **Interaction Summaries** — the `InteractionSummaryPref` org preference (already covered
595
+ as one of the standard toggles above — see "Fundraising feature toggles" for the write
596
+ path, live-tested enable/disable behavior, and the access-check caveat) plus assigning the
597
+ relevant permission set license.
598
+ - **Record Alerts** — two independent parts: the category is automated, the org preferences are
599
+ manual guidance.
600
+ 1. **Category creation** (Tooling API, not Metadata API or the Data API). No dedicated skill covers this create yet, so the mechanics are here: check for an existing
601
+ row first with `dispatch_readonly` `GET /services/data/vXX.0/tooling/query` (`XX` = the org's current API
602
+ version, as for every other versioned path in this skill), `queryParams`
603
+ `{"q": "SELECT Id, DeveloperName, MasterLabel, Description, Severity FROM
604
+ RecordAlertCategory"}`. If a row with the intended `DeveloperName` exists, treat it as already
605
+ satisfied. Otherwise `dispatch` `POST /services/data/vXX.0/tooling/sobjects/RecordAlertCategory`
606
+ (`describe` first, as for any write) with:
607
+
608
+ ```json
609
+ {
610
+ "FullName": "<Developer_Name_From_Label>",
611
+ "Metadata": {
612
+ "masterLabel": "<admin-provided label>",
613
+ "description": "<admin-provided description>",
614
+ "severity": "<Error|Warning|Info>"
615
+ }
616
+ }
617
+ ```
618
+
619
+ `FullName` is create-only and becomes `DeveloperName`; `Metadata` carries all the content.
620
+ `severity` is one of `Error`, `Warning`, `Info`. The key is `masterLabel`, **not** `label` —
621
+ `label` fails with `XML_PARSER_ERROR`. `DeveloperName`, `MasterLabel`, `Description`,
622
+ `Severity` and `Language` are read-only projections you can query but not write. A successful
623
+ create returns `201` with `{"id": "0qX...", "success": true}`; re-run the query above and
624
+ confirm all four fields match before reporting it done.
625
+
626
+ Every value above is a placeholder, not a default. **Never create a category
627
+ unless the admin has supplied its name in this run.** If the admin selects Record Alerts in the
628
+ combined step 12 ask, follow up with one `AskUserQuestion` that asks for the category's label
629
+ (free text) and description, and offers severity as a choice of exactly `Error`, `Warning` or
630
+ `Info`; derive `FullName` from the label. If no name is given, skip creation and report it as
631
+ skipped — do not substitute a made-up or example name. Covered by the `FundraisingAccess` permission set from step 6.
632
+ 2. **Org preferences — manual guidance only**: no API route exists today for
633
+ the Record Alert org preferences, so never probe for one or write them. If the admin opts in at step 12, direct them to complete the steps on the Setup **Record
634
+ Alert Setup** page (`/lightning/setup/RecordAlertSetup/home`) themselves, and record
635
+ `optionalFeatures.recordAlerts.orgPrefsOutcome = "manual_guidance_given"`. Do not infer a
636
+ license gap from anything here; only the admin's own report from that page could establish one
637
+ (`license_gap`). This part never places the Record Alert Lightning component on a page.
638
+ - **Life Events** — the `LifeEventsAccessPSL` permission set license + a permission set assignment
639
+ are the only automated part (same mechanism as any other permission set/license grant, no
640
+ separate handling). Everything else is **manual guidance only — never an automated deploy.** The Setup **Life Events** page
641
+ (`/lightning/setup/LifeEventsSetup/home`) is a checklist, not a wizard that performs actions:
642
+ adding the Business Milestones and Person Life Events related lists, adding the Life
643
+ Events/Business Milestones component to a record page, and creating/activating event or milestone
644
+ types are all manual to-dos with "Show Me How in Help" links out to documentation. Page layout
645
+ and Lightning-page placement have no API or automatable route, so if the admin opts in at step 12,
646
+ direct them to complete the steps on that page themselves and never offer to do it for them. The
647
+ `BusinessMilestone` object's own records remain fully Data-API-writable — only the
648
+ page-layout/component placement and type setup are manual.
649
+ - **Timeline** — this is not a plain settings toggle and does not go through any metadata write.
650
+ It is owned by the approved `Timeline` skill: `describe` it and follow its enable step and the
651
+ verification it defines, plus its configuration lifecycle (create or update, activate or
652
+ deactivate, delete) when configs are needed. Don't restate its routes here. **Only the initial
653
+ enable is treated as irreversible** — give that step its own explicit warning and a separate,
654
+ specific confirmation in addition to the combined ask above; do not enable it on a bare "yes" to
655
+ the combined feature list alone. Name the feature simply "Timeline" when asking the admin to
656
+ confirm. The configs created afterward are ordinary CRUD and don't need the same treatment. This
657
+ skill never automates Lightning-page component placement; if visual placement is needed, it's
658
+ manual guidance like Life Events above, never an automated deploy.
659
+
660
+ Report exactly which of the offered features were actually enabled (and which were skipped or hit
661
+ a confirmed gap) in the final summary — do not assume "offered" implies "enabled."
662
+
663
+ ---
664
+
665
+ ## Error taxonomy
666
+
667
+ | Status / symptom | Likely cause | Action |
668
+ |---|---|---|
669
+ | `401` | headless-360 MCP client not authenticated to the target org | Halt, surface raw error — session needs re-auth |
670
+ | `local_rate_limited` on `discover` | H360 MCP server-side rate limit — distinct from the LLM gateway's own rate limiting, and not a "no match" | Not fatal: fall back to direct `dispatch_readonly` probes for standard Data API objects; retry after a short delay for Metadata-API-only constructs (`FundraisingConfig`) that have no direct-probe fallback |
671
+ | `403` | Executing user missing a required permission | Halt, report exactly which permission is implicated |
672
+ | `404` on a Fundraising-specific route | Org not licensed for Fundraising, or the object/field doesn't exist at this API version | Treat as a licensing/prerequisite failure, not a routing bug — do not retry with guessed alternate paths |
673
+ | `404` on a core Data API path (`/query`, `/sobjects/<Type>`) | Wrong path or typo — these are always present | Re-check the path against `describe`/documentation before retrying |
674
+ | `400 INVALID_TYPE` on `SELECT ... FROM GiftDesignation` | Fundraising org preference is off, so the package's sObjects (`GiftDesignation`) aren't provisioned yet — not a licensing or path problem | Check `orgPreferenceEnabled` via `get-settings-view-model`; if `false`, treat as the same capability gap as the `IndustriesSettings` enablement block, not a separate bug |
675
+ | `400` on a `dispatch` write | Body doesn't match the schema | Re-`describe` the operation and correct the body — do not retry blindly |
676
+ | `200` on a create, but a later verification query shows the record/flag unchanged | A downstream validation rule silently rejected the change | Report as a failure — never trust the write response alone |
677
+ | `500` on a `dispatch` write (e.g. `PermissionSetAssignment` create) | Can be a genuine failure, **or** a false negative — seen live: a `500` on every attempt, but the record existed on read-back | Never report failure from the write response alone either — re-verify with a read-only query before concluding the write didn't take |
678
+ | `DUPLICATE_VALUE` on a `PermissionSetAssignment`/group-assignment or default `GiftDesignation` create | This skill has no persisted resume state by design — every invocation, whether resuming the same paused session or starting fresh days later, replays Phase 1–3 from the top against live org state, and can re-attempt a write that already succeeded | Query for an existing match (`AssigneeId` + `PermissionSetId`/`PermissionSetGroupId`, or `IsDefault = true` for `GiftDesignation`) before creating; treat a match as already-satisfied, not a failure |