@salesforce/afv-skills 1.23.0 → 1.25.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 (61) hide show
  1. package/package.json +1 -1
  2. package/skills/commerce-b2b-open-code-components-replace/SKILL.md +244 -0
  3. package/skills/commerce-b2b-open-code-components-replace/assets/ootb-to-open-code-mapping.json +66 -0
  4. package/skills/{developing-datacloud-code-extension → data360-code-extension-generate}/SKILL.md +7 -7
  5. package/skills/{developing-datacloud-code-extension → data360-code-extension-generate}/references/README.md +7 -7
  6. package/skills/{developing-datacloud-code-extension → data360-code-extension-generate}/references/quick-reference.md +2 -2
  7. package/skills/{getting-datacloud-schema → data360-schema-get}/SKILL.md +26 -26
  8. package/skills/{getting-datacloud-schema → data360-schema-get}/references/README.md +9 -9
  9. package/skills/dx-org-manage/SKILL.md +192 -0
  10. package/skills/dx-org-manage/examples/README.md +45 -0
  11. package/skills/dx-org-manage/examples/scratch-orgs/error_no_devhub.json +9 -0
  12. package/skills/dx-org-manage/examples/scratch-orgs/error_timeout.json +13 -0
  13. package/skills/dx-org-manage/examples/scratch-orgs/success_definition_file.json +28 -0
  14. package/skills/dx-org-manage/examples/scratch-orgs/success_edition.json +26 -0
  15. package/skills/dx-org-manage/examples/scratch-orgs/success_snapshot.json +27 -0
  16. package/skills/dx-org-manage/examples/snapshots/error_output.json +9 -0
  17. package/skills/dx-org-manage/examples/snapshots/success_output.json +15 -0
  18. package/skills/dx-org-manage/references/cli_flags.md +67 -0
  19. package/skills/dx-org-manage/references/creating-scratch-org.md +164 -0
  20. package/skills/dx-org-manage/references/creating-snapshot.md +103 -0
  21. package/skills/dx-org-manage/references/definition_file_options.md +224 -0
  22. package/skills/dx-org-manage/references/edition_types.md +78 -0
  23. package/skills/dx-org-manage/references/opening-org.md +160 -0
  24. package/skills/dx-org-manage/references/snapshot_usage.md +74 -0
  25. package/skills/dx-org-permission-set-assign/SKILL.md +98 -0
  26. package/skills/dx-org-permission-set-assign/examples/error_output.json +19 -0
  27. package/skills/dx-org-permission-set-assign/examples/success_output.json +16 -0
  28. package/skills/dx-org-permission-set-assign/references/cli_flags.md +68 -0
  29. package/skills/experience-cms-brand-apply/SKILL.md +1 -1
  30. package/skills/experience-ui-bundle-app-coordinate/SKILL.md +31 -19
  31. package/skills/experience-ui-bundle-file-upload-generate/SKILL.md +1 -1
  32. package/skills/experience-ui-bundle-frontend-generate/implementation/header-footer.md +1 -1
  33. package/skills/experience-ui-bundle-salesforce-data-access/SKILL.md +336 -581
  34. package/skills/experience-ui-bundle-salesforce-data-access/references/caching.md +172 -0
  35. package/skills/experience-ui-bundle-salesforce-data-access/references/graphiti-cli.md +373 -0
  36. package/skills/experience-ui-bundle-salesforce-data-access/references/graphql-hand-authoring.md +376 -0
  37. package/skills/experience-ui-bundle-salesforce-data-access/references/migration.md +119 -0
  38. package/skills/experience-ui-bundle-salesforce-data-access/references/rest-and-integration.md +152 -0
  39. package/skills/experience-ui-bundle-salesforce-data-access/references/sdk-api.md +217 -0
  40. package/skills/experience-ui-bundle-salesforce-data-access/scripts/graphql-search.sh +36 -9
  41. package/skills/platform-agentsetup-categories-fetch/SKILL.md +109 -0
  42. package/skills/platform-agentsetup-categories-fetch/references/api-response-schema.md +121 -0
  43. package/skills/platform-custom-object-generate/SKILL.md +62 -7
  44. package/skills/platform-custom-object-generate/references/description-enrichment.md +125 -0
  45. package/skills/platform-metadata-retrieve/SKILL.md +121 -0
  46. package/skills/platform-metadata-retrieve/examples/error_output.json +10 -0
  47. package/skills/platform-metadata-retrieve/examples/success_output.json +27 -0
  48. package/skills/platform-metadata-retrieve/references/cli_flags.md +138 -0
  49. package/skills/platform-metadata-retrieve/references/retrieval_modes.md +181 -0
  50. package/skills/platform-sharing-rules-generate/SKILL.md +165 -0
  51. package/skills/platform-sharing-rules-generate/references/rule-types.md +199 -0
  52. package/skills/platform-tracing-agentforce-configure/SKILL.md +118 -0
  53. package/skills/platform-tracing-agentforce-configure/assets/AgentforcePlatformTracing-template.xml +4 -0
  54. package/skills/platform-tracing-configure/SKILL.md +118 -0
  55. package/skills/platform-tracing-configure/assets/EventSettings-template.xml +4 -0
  56. package/skills/platform-trust-archive-manage/SKILL.md +25 -11
  57. package/skills/platform-trust-archive-manage/examples/monitor-failed-jobs.md +2 -2
  58. package/skills/platform-trust-archive-manage/references/archive-activity-entity.md +1 -1
  59. package/skills/platform-trust-archive-manage/references/connect-api-operations.md +51 -12
  60. /package/skills/{getting-datacloud-schema → data360-schema-get}/scripts/get_dlo_schema.py +0 -0
  61. /package/skills/{getting-datacloud-schema → data360-schema-get}/scripts/get_dmo_schema.py +0 -0
@@ -0,0 +1,217 @@
1
+ # The Data SDK call API (`@salesforce/platform-sdk`)
2
+
3
+ The `query`/`mutate` namespace, typing, and error handling. For caching and the reactive
4
+ refresh modes see [caching.md](caching.md); for old→new conversion see [migration.md](migration.md).
5
+
6
+ ## Import
7
+
8
+ ```typescript
9
+ import { createDataSDK, gql, type CacheControl, type NodeOfConnection } from "@salesforce/platform-sdk";
10
+ ```
11
+
12
+ `createDataSDK`, `gql`, `CacheControl`, and `NodeOfConnection` all come from
13
+ **`@salesforce/platform-sdk`**. The old `@salesforce/sdk-data` package name is dead — any
14
+ `@salesforce/sdk-data` string you see in the repo is a stale `dist/` build artifact, not the
15
+ canonical import.
16
+
17
+ ## `sdk.graphql` is a NAMESPACE, not a callable
18
+
19
+ The previous SDK exposed `sdk.graphql` as a callable: `await sdk.graphql?.(query, vars)`.
20
+ That form is gone. `sdk.graphql` is now a namespace with two methods:
21
+
22
+ ```typescript
23
+ const sdk = await createDataSDK();
24
+
25
+ // QUERY — reactive, cached on WebApp
26
+ const result = await sdk.graphql!.query<TData, TVariables>({
27
+ query: MY_QUERY, // gql-tagged string (the `query` key)
28
+ variables, // optional
29
+ operationName, // optional
30
+ cacheControl, // optional — see caching.md
31
+ });
32
+
33
+ // MUTATE — request/response, never cached
34
+ const { data, errors } = await sdk.graphql!.mutate<TData, TVariables>({
35
+ mutation: MY_MUTATION, // NOTE: the key is `mutation`, not `query`
36
+ variables,
37
+ operationName,
38
+ });
39
+ ```
40
+
41
+ Type signatures (from `core/data.ts`):
42
+
43
+ ```typescript
44
+ query<T, V>(options: QueryOptions<V>): Promise<QueryResult<T>>;
45
+ mutate<T, V>(options: MutateOptions<V>): Promise<MutationResult<T>>;
46
+ ```
47
+
48
+ ### `sdk.graphql!` vs guard
49
+
50
+ `sdk.graphql` may still be `undefined` on surfaces that do not support data operations, so it
51
+ is typed `graphql?: DataSDKGraphQL`. Real consumer code asserts it is present after
52
+ `createDataSDK()` with the non-null assertion:
53
+
54
+ ```typescript
55
+ const result = await sdk.graphql!.query<...>({ query, variables });
56
+ ```
57
+
58
+ This replaces the old optional-call `sdk.graphql?.(...)`. Do **not** reach for the dead
59
+ callable form. Which of `!` vs a guard you use is a **surface decision** (the spine's
60
+ [Surfaces](../SKILL.md#surfaces--sdkgraphql-vs-guard) table is the routing): `!` only if the
61
+ bundle is WebApp-exclusive; otherwise guard, because a bare `sdk.graphql!` that later ships to
62
+ another surface throws `Cannot read properties of undefined` at runtime — TypeScript won't catch
63
+ it because `!` silences exactly that check.
64
+
65
+ ```typescript
66
+ // `!` form — WebApp-only bundles; every shipped WebApp consumer uses it.
67
+ const result = await sdk.graphql!.query<...>({ query, variables });
68
+
69
+ // Portable guard form — safe on every surface. Use when the bundle is not WebApp-exclusive.
70
+ if (!sdk.graphql) {
71
+ // No data SDK on this surface — degrade gracefully (render empty, throw, or feature-flag off).
72
+ return;
73
+ }
74
+ const result = await sdk.graphql.query<...>({ query, variables });
75
+ ```
76
+
77
+ (The same `!`-vs-guard call applies to `sdk.fetch!`.)
78
+
79
+ ## `QueryResult<T>` — the reactive query handle
80
+
81
+ `query()` resolves to a `QueryResult<T>`, which IS a snapshot AND carries two reactive methods:
82
+
83
+ ```typescript
84
+ interface QuerySnapshot<T> { data: T | undefined; errors?: GraphQLError[]; }
85
+ type QuerySubscriber<T> = (snapshot: QuerySnapshot<T>) => void;
86
+ type Unsubscribe = () => void;
87
+
88
+ interface QueryResult<T> extends QuerySnapshot<T> {
89
+ subscribe(cb: QuerySubscriber<T>): Unsubscribe;
90
+ refresh(): Promise<void>;
91
+ }
92
+ ```
93
+
94
+ - `result.data` / `result.errors` — the initial snapshot at await-time (cached value on cached
95
+ surfaces, else the network response).
96
+ - `result.subscribe(cb)` — register a callback for every *subsequent* snapshot (a cache update,
97
+ a stale-while-revalidate refill, or an explicit `refresh()`). Returns an `Unsubscribe`. Each
98
+ `subscribe` is **independent** — unsubscribing one leaves the others live — and it does **not**
99
+ fire on registration, only on later snapshots.
100
+ - `result.refresh()` — re-issue the request bypassing the cache, write the fresh result back, and
101
+ push the new snapshot to **all** current subscribers. Returns `Promise<void>`.
102
+
103
+ *When* to reach for `subscribe`/`refresh` over the default cache, plus the uncached-surface
104
+ caveats, is a strategy call — see [caching.md](caching.md).
105
+
106
+ ## `cacheControl` — the per-call cache policy
107
+
108
+ `cacheControl` is an optional field on the query options bag. It overrides the default cache
109
+ behavior for **one** call and does **not** change the cache key, so a `"no-cache"` call and a
110
+ default call read/write the *same* cache slot. The type:
111
+
112
+ ```typescript
113
+ type CacheControlShorthand = "no-cache" | "only-if-cached";
114
+ interface CacheControlMaxAge { type: "max-age"; maxAge: number; }
115
+ type CacheControl = CacheControlShorthand | CacheControlMaxAge;
116
+ ```
117
+
118
+ | `cacheControl` | Behavior |
119
+ |---|---|
120
+ | *(omitted)* | Default — return the cached entry if fresh (300s TTL), else fetch and write back. |
121
+ | `"no-cache"` | Skip the cache **read**, always hit the network. **Still writes the response back** for later default callers. |
122
+ | `"only-if-cached"` | Read from cache **only**. Hit → return; **miss → `DataNotFoundError` on `result.errors`** (no network, no throw). |
123
+ | `{ type: "max-age", maxAge: <seconds> }` | Custom TTL instead of 300s. `maxAge: 0` = written but immediately stale; invalid values silently fall back to 300s. |
124
+
125
+ An `only-if-cached` miss is not an exception — the Promise resolves and the miss surfaces on
126
+ `result.errors` as a `DataNotFoundError`. This is offline-first: a miss is **expected, not an
127
+ error**. Check `result.errors`, render an empty state, and **do not fall back to a network read**
128
+ — a fallback defeats the point of `only-if-cached`:
129
+
130
+ ```typescript
131
+ const result = await sdk.graphql!.query({ query: GET_ACCOUNTS, variables, cacheControl: "only-if-cached" });
132
+ if (result.errors?.length) {
133
+ // cold cache — render the empty state. Do NOT fall back to the network; that defeats offline-first.
134
+ return renderEmptyState();
135
+ }
136
+ ```
137
+
138
+ Which policy fits which goal (force-refresh button, offline-first, fast-changing data) is a
139
+ strategy call — see the decision matrix in [caching.md](caching.md).
140
+
141
+ ## `MutationResult<T>` — one-shot, NO subscribe/refresh
142
+
143
+ ```typescript
144
+ interface MutationResult<T> { data: T | undefined; errors?: GraphQLError[]; }
145
+ ```
146
+
147
+ Mutations are request/response. The type deliberately has **no** `subscribe` and **no**
148
+ `refresh` — mutating on subscribe is incoherent, and re-running a mutation on refresh is
149
+ dangerous. To refresh data after a mutation, hold a query `result` and call `result.refresh()`
150
+ (see [caching.md](caching.md)).
151
+
152
+ ## HTTP 200 ≠ success — always read `errors`
153
+
154
+ The Promise resolves even for GraphQL/parse errors; they surface on `result.errors`, never as a
155
+ thrown exception from `query()`/`mutate()`. Both shipped consumers gate on `errors` first:
156
+
157
+ ```typescript
158
+ // accounts.ts pattern
159
+ if (result.errors?.length) {
160
+ throw new Error(result.errors.map((e) => e.message).join("; "));
161
+ }
162
+ ```
163
+
164
+ ```typescript
165
+ // graphqlClient.ts (canonical scaffold) — strict wrapper
166
+ export async function executeGraphQL<TData, TVariables>(
167
+ query: string,
168
+ variables?: TVariables,
169
+ ): Promise<TData> {
170
+ const sdk = await createDataSDK();
171
+ const result = await sdk.graphql!.query<TData, TVariables>({ query, variables });
172
+ if (result.errors?.length) {
173
+ throw new Error(`GraphQL Error: ${result.errors.map((e) => e.message).join("; ")}`);
174
+ }
175
+ if (result.data == null) {
176
+ throw new Error("GraphQL response data is null");
177
+ }
178
+ return result.data;
179
+ }
180
+ ```
181
+
182
+ Three error-handling stances (all read `result.errors`):
183
+
184
+ ```typescript
185
+ // Strict — any errors = failure
186
+ if (result.errors?.length) throw new Error(result.errors.map((e) => e.message).join("; "));
187
+
188
+ // Tolerant — log, use whatever data came back (partial success)
189
+ if (result.errors?.length) console.warn("GraphQL partial errors:", result.errors);
190
+
191
+ // Discriminated — fail only when NO data returned
192
+ if (!result.data && result.errors?.length) {
193
+ throw new Error(result.errors.map((e) => e.message).join("; "));
194
+ }
195
+ ```
196
+
197
+ ## Generated types on the call
198
+
199
+ After `npm run graphql:codegen`, import the generated `<Op>Query` / `<Op>QueryVariables` types
200
+ and pass them as the type parameters. The call shape changed — types now go on `.query()`, not
201
+ the old callable:
202
+
203
+ ```typescript
204
+ import type { GetAccountsQuery, GetAccountsQueryVariables } from "../graphql-operations-types";
205
+
206
+ const result = await sdk.graphql!.query<GetAccountsQuery, GetAccountsQueryVariables>({
207
+ query: GET_ACCOUNTS,
208
+ variables,
209
+ });
210
+ ```
211
+
212
+ `NodeOfConnection<T>` extracts a node type from a Connection for cleaner typing:
213
+
214
+ ```typescript
215
+ import { type NodeOfConnection } from "@salesforce/platform-sdk";
216
+ type AccountNode = NodeOfConnection<GetAccountsQuery["uiapi"]["query"]["Account"]>;
217
+ ```
@@ -2,13 +2,20 @@
2
2
  set -euo pipefail # exit on error (-e), undefined vars (-u), and propagate pipeline failures (-o pipefail)
3
3
  # graphql-search.sh — Look up one or more Salesforce entities in schema.graphql.
4
4
  #
5
- # Run from the SFDX project root (where schema.graphql lives):
6
- # bash scripts/graphql-search.sh Account
7
- # bash scripts/graphql-search.sh Account Contact Opportunity
5
+ # Run from the SFDX project root, where schema.graphql lives:
6
+ # bash <skill-dir>/scripts/graphql-search.sh Account
7
+ # bash <skill-dir>/scripts/graphql-search.sh Account Contact Opportunity
8
8
  #
9
- # Pass a custom schema path with -s / --schema:
10
- # bash scripts/graphql-search.sh -s /path/to/schema.graphql Account
11
- # bash scripts/graphql-search.sh --schema ./other/schema.graphql Account Contact
9
+ # The script does NOT search up the directory tree — an ancestor schema.graphql
10
+ # may belong to a DIFFERENT org, and silently matching it would validate fields
11
+ # against the wrong schema. If schema.graphql is not at ./ you must point the
12
+ # script at the right file explicitly (resolution order, first hit wins):
13
+ # 1. -s / --schema <path> explicit flag
14
+ # 2. $GRAPHQL_SCHEMA env var explicit override
15
+ # 3. ./schema.graphql (current working directory only)
16
+ #
17
+ # bash <skill-dir>/scripts/graphql-search.sh -s force-app/main/default/uiBundles/<app>/schema.graphql Account
18
+ # GRAPHQL_SCHEMA=/abs/path/schema.graphql bash <skill-dir>/scripts/graphql-search.sh Account
12
19
  #
13
20
  # Output sections per entity:
14
21
  # 1. Type definition — all fields and relationships
@@ -19,7 +26,7 @@ set -euo pipefail # exit on error (-e), undefined vars (-u), and propagate pipe
19
26
  # 6. Update mutation wrapper — <Entity>UpdateInput
20
27
  # 7. Update mutation fields — <Entity>UpdateRepresentation (for update mutations)
21
28
 
22
- SCHEMA="./schema.graphql"
29
+ SCHEMA=""
23
30
 
24
31
  # ── Argument parsing ─────────────────────────────────────────────────────────
25
32
 
@@ -56,10 +63,26 @@ if [ $# -eq 0 ]; then
56
63
  exit 1
57
64
  fi
58
65
 
66
+ # ── Schema resolution ────────────────────────────────────────────────────────
67
+ # NO directory walk-up: resolve only from an explicit flag, an explicit env var,
68
+ # or schema.graphql in the CURRENT directory. Searching ancestors risks matching
69
+ # an unrelated project's schema and validating fields against the wrong org.
70
+ # Resolution order (first hit wins): -s/--schema, then $GRAPHQL_SCHEMA, then ./schema.graphql.
71
+
72
+ if [ -z "$SCHEMA" ] && [ -n "${GRAPHQL_SCHEMA-}" ]; then
73
+ SCHEMA="$GRAPHQL_SCHEMA"
74
+ fi
75
+
76
+ if [ -z "$SCHEMA" ]; then
77
+ SCHEMA="./schema.graphql"
78
+ fi
79
+
59
80
  if [ ! -f "$SCHEMA" ]; then
60
- echo "ERROR: schema.graphql not found at $SCHEMA"
61
- echo " Make sure you are running from the SFDX project root, or pass the path explicitly:"
81
+ echo "ERROR: schema.graphql not found at '$SCHEMA'."
82
+ echo " This script does NOT search parent directories (an ancestor schema may be the wrong org's)."
83
+ echo " Run from the SFDX project root where schema.graphql lives, or point at it explicitly:"
62
84
  echo " bash $0 --schema <path/to/schema.graphql> <EntityName>"
85
+ echo " GRAPHQL_SCHEMA=<path/to/schema.graphql> bash $0 <EntityName>"
63
86
  echo " If the file is missing entirely, generate it from the UI bundle dir:"
64
87
  echo " cd force-app/main/default/uiBundles/<app-name> && npm run graphql:schema"
65
88
  exit 1
@@ -78,6 +101,10 @@ if [ ! -s "$SCHEMA" ]; then
78
101
  exit 1
79
102
  fi
80
103
 
104
+ # Announce the resolved schema so a wrong-file match is visible, not silent.
105
+ # stderr keeps it out of the parsed lookup output on stdout.
106
+ echo "[graphql-search] using schema: $SCHEMA" >&2
107
+
81
108
  # ── Helper: extract lines from a grep match through the closing brace ────────
82
109
  # Prints up to MAX_LINES lines after (and including) the first match of PATTERN.
83
110
  # Uses a generous line count — blocks are always closed by a "}" line.
@@ -0,0 +1,109 @@
1
+ ---
2
+ name: platform-agentsetup-categories-fetch
3
+ description: "Fetch agentic setup prompt categories from a connected Salesforce org using the Connect API. Use this skill to call GET /agenticsetup/categories and return the list of prompt categories, optionally with their nested prompts. TRIGGER when: user asks to get, fetch, list, or show agentic setup categories, prompt categories, setup copilot categories, prompt library categories, available setup prompts, Agentforce prompt library, or copilot prompts. DO NOT TRIGGER when: user wants to create new categories, work with non-categories endpoints, or generate OpenAPI specs."
4
+ allowed-tools: Bash Read
5
+ metadata:
6
+ version: "1.0"
7
+ minApiVersion: "67.0"
8
+ ---
9
+
10
+ # platform-agentsetup-categories-fetch
11
+
12
+ Fetch prompt categories from the Agentic Setup Categories Connect API on a connected Salesforce org.
13
+
14
+ ## Scope
15
+
16
+ **In scope:**
17
+ - Calling `GET /services/data/{apiVersion}/agenticsetup/categories` via SF CLI
18
+ - Passing the `fetchPrompts` query parameter to include nested prompts
19
+ - Parsing and presenting the JSON response (categories, labels, prompts)
20
+ - Handling errors (403 when feature is disabled, auth failures)
21
+
22
+ **Out of scope — delegate elsewhere:**
23
+ - Creating or modifying prompt categories → not supported via this API (read-only)
24
+ - Org authentication setup → use `sf org login` separately
25
+ - Permission set assignment → assigning-permission-set
26
+
27
+ ---
28
+
29
+ ## Required Inputs
30
+
31
+ The agent needs:
32
+ - A connected org (already authenticated via `sf org login`)
33
+ - Optionally: whether to include nested prompts (`fetchPrompts=true`)
34
+ - Optionally: target API version (default: v67.0). Replace `v67.0` in the URL with the user-specified version if provided.
35
+
36
+ ---
37
+
38
+ ## Workflow
39
+
40
+ ### 1. Verify org connectivity
41
+
42
+ ```bash
43
+ sf org display --json
44
+ ```
45
+
46
+ Confirm the org is authenticated and extract the instance URL. If no default org is set, ask the user which org to target with `--target-org`.
47
+
48
+ ### 2. Call the Categories API
49
+
50
+ **Basic call (categories only):**
51
+ ```bash
52
+ sf api request rest /services/data/v67.0/agenticsetup/categories --method GET
53
+ ```
54
+
55
+ **With nested prompts:**
56
+ ```bash
57
+ sf api request rest "/services/data/v67.0/agenticsetup/categories?fetchPrompts=true" --method GET
58
+ ```
59
+
60
+ ### 3. Parse and present the response
61
+
62
+ The API returns a JSON object with a `categories` array. Each category has `name`, `label`, and `prompts` fields. See `references/api-response-schema.md` for the full response structure and examples for both `fetchPrompts=true` and `fetchPrompts=false`.
63
+
64
+ Present the results clearly:
65
+ - List categories with their name and label
66
+ - If `fetchPrompts=true` was used, show nested prompts under each category
67
+ - Note any categories with empty `prompts` arrays (means no prompts exist for that category)
68
+
69
+ ### 4. Handle errors
70
+
71
+ | Error | Meaning | Action |
72
+ |-------|---------|--------|
73
+ | Success (exit 0) | 200 OK | Parse and display results |
74
+ | `FUNCTIONALITY_NOT_ENABLED` | Feature not enabled for this org/user | Tell user the Agentic Setup Categories feature needs to be enabled — check Setup > Einstein/Agentforce |
75
+ | `INVALID_SESSION_ID` | Session expired | Re-authenticate with `sf org login` |
76
+ | `NOT_FOUND` | Endpoint not found | API version too old or feature not deployed to this org |
77
+
78
+ ---
79
+
80
+ ## Rules / Constraints
81
+
82
+ | Rule | Rationale |
83
+ |------|-----------|
84
+ | Always use `sf api request rest` — never curl or raw HTTP | curl bypasses `~/.sfdx` session tokens and requires manual Authorization headers, making it brittle |
85
+ | NEVER use SOQL queries | Categories are NOT in standard objects — only available via this Connect REST API |
86
+ | NEVER generate files (LWC, Apex, XML) | This is a data-fetching task, not a code generation task |
87
+ | Default to v67.0 unless user specifies | This is the min-version where the endpoint was introduced |
88
+ | Don't pass fetchPrompts unless asked | Reduces payload size; prompts can be large |
89
+ | Categories are sorted by label | The API returns them alphabetically — don't re-sort |
90
+ | Prompts are sorted by text | Within each category, prompts come alphabetically |
91
+
92
+ ---
93
+
94
+ ## Output Expectations
95
+
96
+ When finishing, present:
97
+
98
+ 1. **Number of categories** returned
99
+ 2. **Category list** — name and label for each
100
+ 3. **Prompts** (if requested) — nested under their category
101
+ 4. **Any errors** encountered with suggested fixes
102
+
103
+ ---
104
+
105
+ ## Reference File Index
106
+
107
+ | File | When to read |
108
+ |------|--------------|
109
+ | `references/api-response-schema.md` | When you need to understand the full response structure and field descriptions |
@@ -0,0 +1,121 @@
1
+ # Agentic Setup Categories API Response Schema
2
+
3
+ ## Endpoint
4
+
5
+ ```text
6
+ GET /services/data/v67.0/agenticsetup/categories
7
+ GET /services/data/v67.0/agenticsetup/categories?fetchPrompts=true
8
+ ```
9
+
10
+ ## Response Structure
11
+
12
+ ### PromptCategoryListRepresentation
13
+
14
+ Top-level response object.
15
+
16
+ | Field | Type | Description |
17
+ |-------|------|-------------|
18
+ | `categories` | array of PromptCategoryRepresentation | Categories sorted alphabetically by localized label |
19
+
20
+ ### PromptCategoryRepresentation
21
+
22
+ A single prompt category.
23
+
24
+ | Field | Type | Description |
25
+ |-------|------|-------------|
26
+ | `name` | string | Stable programmatic identifier (e.g., "UserManagement") |
27
+ | `label` | string | Localized display label (e.g., "User Management") |
28
+ | `prompts` | array of PromptRepresentation | Populated when `fetchPrompts=true`; empty array otherwise |
29
+
30
+ ### PromptRepresentation
31
+
32
+ A single prompt entry within a category.
33
+
34
+ | Field | Type | Description |
35
+ |-------|------|-------------|
36
+ | `text` | string | User-facing prompt text to display and pass to the LLM |
37
+ | `description` | string | Short helper description shown next to the prompt |
38
+
39
+ ## Example Response (fetchPrompts=false)
40
+
41
+ ```json
42
+ {
43
+ "categories": [
44
+ {
45
+ "label": "Flow Management",
46
+ "name": "FlowManagement",
47
+ "prompts": []
48
+ },
49
+ {
50
+ "label": "Identity",
51
+ "name": "Identity",
52
+ "prompts": []
53
+ },
54
+ {
55
+ "label": "User Management",
56
+ "name": "UserManagement",
57
+ "prompts": []
58
+ }
59
+ ]
60
+ }
61
+ ```
62
+
63
+ ## Example Response (fetchPrompts=true)
64
+
65
+ ```json
66
+ {
67
+ "categories": [
68
+ {
69
+ "label": "Flow Management",
70
+ "name": "FlowManagement",
71
+ "prompts": [
72
+ {
73
+ "description": "Scaffold a new flow",
74
+ "text": "Design a flow that [describe trigger and outcome]."
75
+ },
76
+ {
77
+ "description": "List active flows",
78
+ "text": "List all active flows in this org. Include the object, trigger type, and last modified date for each."
79
+ }
80
+ ]
81
+ },
82
+ {
83
+ "label": "User Management",
84
+ "name": "UserManagement",
85
+ "prompts": [
86
+ {
87
+ "description": "Activate a user",
88
+ "text": "Activate user [user]. Confirm what becomes accessible to them again and whether their license is still available."
89
+ },
90
+ {
91
+ "description": "Clone a user",
92
+ "text": "Clone [existing user] to create a new user for [new person's name and email]."
93
+ }
94
+ ]
95
+ }
96
+ ]
97
+ }
98
+ ```
99
+
100
+ ## Error Responses
101
+
102
+ ### FUNCTIONALITY_NOT_ENABLED
103
+
104
+ Returned when the Agentic Setup Categories feature is not enabled on the org.
105
+
106
+ ```json
107
+ [
108
+ {
109
+ "message": "This feature is not currently enabled for this user type or org: [AgenticSetupCategoriesApiFamily]",
110
+ "errorCode": "FUNCTIONALITY_NOT_ENABLED"
111
+ }
112
+ ]
113
+ ```
114
+
115
+ ### Access Requirements
116
+
117
+ The endpoint uses a two-tier security model:
118
+ 1. **Org-level**: `SetupCopilot.orgHasEnhancedAgenticSetup` must be true
119
+ 2. **User-level**: `SetupCopilot.orgHasSetupHomePromptLibrary` must be true per request
120
+
121
+ If either check fails, the API returns `FUNCTIONALITY_NOT_ENABLED`.
@@ -1,8 +1,9 @@
1
1
  ---
2
2
  name: platform-custom-object-generate
3
- description: "Use this skill when users need to create, generate, or validate Salesforce Custom Object metadata. Trigger when users mention custom objects, creating objects, object metadata, .object files, sharing models, name fields, or validation rules on objects. Also use when users say things like \"create a custom object\", \"generate object metadata\", \"set up an object for...\", or when they're troubleshooting object deployment errors especially around sharing models and Master-Detail relationships. Always use this skill for any custom object metadata work."
3
+ description: "Use this skill when users need to create, generate, or validate Salesforce Custom Object metadata. Trigger when users mention custom objects, creating objects, object metadata, .object files, sharing models, name fields, or validation rules on objects. Also use when users say things like \"create a custom object\", \"generate object metadata\", \"set up an object for...\", or when they're troubleshooting object deployment errors especially around sharing models and Master-Detail relationships. Always use this skill for any custom object metadata work, including enriching and keeping the object's description current whenever its fields or validation rules change. Do NOT use this skill for non-Custom-Object metadata (Apex, Flows, LWC, Permission Sets, Custom Metadata Types) or for standard Salesforce objects."
4
4
  metadata:
5
- version: "1.0"
5
+ version: "1.1"
6
+ minApiVersion: "60.0"
6
7
  ---
7
8
 
8
9
  ## When to Use This Skill
@@ -13,6 +14,7 @@ Use this skill when you need to:
13
14
  - Configure object sharing and security settings
14
15
  - Set up object features and capabilities
15
16
  - Troubleshoot deployment errors related to custom objects
17
+ - **Add, update, or delete a field OR a validation rule on an existing object** — any of these may make the object's `<description>` stale, so you must refresh it (propose + confirm). This applies equally to validation-rule changes, not just fields. See Section 3.B.
16
18
 
17
19
  ## Specification
18
20
 
@@ -22,6 +24,8 @@ This document defines the mandatory constraints for generating CustomObject meta
22
24
 
23
25
  **File extension:** `.object-meta.xml`
24
26
 
27
+ > **🔔 Description freshness — applies to EVERY object change, fields AND validation rules:** Whenever you add, update, or delete a field **or a validation rule** on an object, the `<description>` may now be stale. Before finishing, refresh it per **Section 3.B** (propose, confirm with the user, write). A validation-rule change counts exactly like a field change — the change is **not** done until the description has been reconciled. This is easy to forget on validation-rule edits/deletes — don't.
28
+
25
29
  ---
26
30
 
27
31
  ## 2. Syntactic Essentials (Tier 1)
@@ -103,12 +107,47 @@ The agent must choose which features to enable based on the object's intended us
103
107
  </nameField>
104
108
  ```
105
109
 
106
- ### B. Object Description
110
+ ### B. Object Description (Enrichment)
111
+
112
+ **`<description>`**: **Mandatory** — every Custom Object MUST have one. It must read like human-written documentation, **never** a generic template ("Object used to track and manage...") or a metadata dump ("Contains 8 fields including `Project_Name__c`...").
113
+
114
+ **Always compose an enriched description** — when creating the object, and again on **any** change to it: adding, updating, or deleting a field **or a validation rule** (so it never goes stale). The change — field or validation rule — is never "done" until you've refreshed the object's description. This is not optional; do not ask *whether* to add a description.
115
+
116
+ **Confirm per change — every time.** Propose and confirm on **each** field/rule change separately. A previous "keep current" applies **only** to that one change; it is **never** standing permission to skip the proposal on a later change. Do not infer a preference from an earlier answer — re-propose and re-ask for every new change.
117
+
118
+ **Compose** the description (steps below). If the object already has one, use it as a **strong signal** — preserve the business context it carries (domain, team, intent the schema can't reveal) and fold the new field/rule in rather than discarding it.
119
+
120
+ Then branch on whether a description already exists:
121
+
122
+ - **No existing description (brand-new object):** there is nothing to overwrite — just write the composed description. **Do not prompt.**
123
+ - **An existing description (update, delete, or any re-enrichment):** never overwrite it silently — you can't tell from the file whether it was hand-written by an admin or generated earlier. Show the proposal, ask, and **STOP — wait for the user's reply before writing:**
124
+ > Proposed description for `{Object}`:
125
+ > `<the enriched description>`
126
+ > Current: `<the existing description>`
127
+ > Use this? (yes / keep current / edit)
128
+
129
+ **You MUST NOT write the `<description>` until the user replies** — showing the diff is not approval, even when the change looks obvious or minor. Then act: *yes* → write the proposed text · *keep current* → leave the existing one untouched (this applies to **this change only** — re-propose on the next one) · *edit* → use the user's wording.
130
+
131
+ Always end with a `<description>` written.
132
+
133
+ **Composing the description:**
107
134
 
108
- **`<description>`**: Mandatory. Every object must contain a professional summary.
135
+ 1. **Classify each field** by how it appears in the description:
136
+ - **Constrained** (required, unique, externalId, restricted picklist) → selective parenthetical: `VIN (required, external ID)`, `Color (Red/Green only)`
137
+ - **Behavioral** (formula, roll-up) → describe what it computes: "the Age Years field auto-calculates vehicle age"
138
+ - **Relationship** (master-detail, lookup) → woven context: "as a child of Account" (never "(Master-Detail to Account)")
139
+ - **Standard** → label only
140
+ 2. **Compose** in this order, using field **labels not API names**:
141
+ > Purpose → key fields → computed fields → validation rules (as business rules) → "Commonly used for {use cases}."
142
+ 3. **Count and trim before writing (required):** count the words; aim ~45, hard ceiling 50. If over, tighten wording first, then drop whole sentences in priority order (use cases → rules → computed; never drop sentences 1–2). Recount. Do not write until ≤ 50.
143
+
144
+ **Example (Car, 46 words):**
145
+ ```xml
146
+ <description>The Car object tracks vehicle inventory and maintenance. It captures Year, VIN (required, external ID), Color (Red/Green only), and Location; the Age Years field auto-calculates vehicle age. VIN is required and Black cars cannot be sold. Commonly used for fleet management, inventory tracking, and service scheduling.</description>
147
+ ```
148
+
149
+ → For the full workflow and examples, read **`references/description-enrichment.md`**.
109
150
 
110
- If the intent is vague, generate a summary:
111
- > "Object used to track and manage [Intent] within the organization."
112
151
  ### C. Junction Object Naming
113
152
 
114
153
  If the object is a many-to-many link between two parents, name the object by combining the two parent entities to ensure the schema remains intuitive.
@@ -234,7 +273,23 @@ Before generating the Custom Object XML, verify:
234
273
  - [ ] Do validation rule names NOT end with `__c`?
235
274
  - [ ] Do validation rule names follow alphanumeric + underscore pattern?
236
275
 
276
+ ### Description Enrichment Quality Checks
277
+ - [ ] Opens with "The {Object} object..." + business purpose (not "Object used to track and manage...")
278
+ - [ ] Uses field **labels**, never API names; no "Contains N fields including" dump
279
+ - [ ] Formulas/rollups described by behavior; validations stated as business rules; relationships as context
280
+ - [ ] Includes common use cases ("Commonly used for...") and is **under 50 words**
281
+ - [ ] Folded any current description's business context into the proposed one (didn't discard it)
282
+ - [ ] For an existing description (update/delete/re-enrich), STOPPED and waited for the user's reply before writing — did not treat showing the diff as approval
283
+
237
284
  ### Architectural Checks
238
- - [ ] Is `<description>` present with a meaningful summary?
285
+ - [ ] Is `<description>` present? (Enriched per Section B — proposed and confirmed with the user before writing.)
239
286
  - [ ] Are `<enableSearch>` and `<enableReports>` set to `true` if user-facing?
240
287
  - [ ] Does the filename match the intended API name?
288
+
289
+ ---
290
+
291
+ ## Reference File Index
292
+
293
+ | File | When to read |
294
+ |------|-------------|
295
+ | `references/description-enrichment.md` | Composing or refreshing an object's `<description>` (on create, or when a field/rule changes) — full enrichment workflow, field-prioritization tiers, junction/child handling, edge cases, and more examples |