@salesforce/afv-skills 1.33.0 → 1.35.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.
- package/package.json +1 -1
- package/skills/agentforce-architecture-analyze/SKILL.md +8 -0
- package/skills/agentforce-bot-upgrade/SKILL.md +0 -2
- package/skills/agentforce-d360-analyze/SKILL.md +8 -0
- package/skills/agentforce-observe/SKILL.md +3 -0
- package/skills/agentforce-test/SKILL.md +3 -0
- package/skills/automation-flow-generate/SKILL.md +1 -0
- package/skills/automation-sandbox-post-copy-config-generate/SKILL.md +239 -0
- package/skills/automation-sandbox-post-copy-config-generate/assets/config_template.json +21 -0
- package/skills/automation-sandbox-post-copy-config-generate/assets/json_schema.json +90 -0
- package/skills/automation-sandbox-post-copy-config-generate/examples/sample_sop_excerpt.md +31 -0
- package/skills/automation-sandbox-post-copy-config-generate/examples/sample_sop_to_config.json +50 -0
- package/skills/automation-sandbox-post-copy-config-generate/references/configuration_catalog.md +76 -0
- package/skills/automation-sandbox-post-copy-config-generate/references/sop_parsing_patterns.md +157 -0
- package/skills/automation-sandbox-post-copy-config-generate/references/source_format_handling.md +230 -0
- package/skills/commerce-b2b-open-code-components-integrate/SKILL.md +8 -0
- package/skills/commerce-b2b-open-code-components-replace/SKILL.md +2 -0
- package/skills/commerce-b2b-store-create/SKILL.md +4 -1
- package/skills/data360-activate/SKILL.md +12 -0
- package/skills/data360-code-extension-generate/SKILL.md +6 -6
- package/skills/data360-connect/SKILL.md +11 -0
- package/skills/data360-harmonize/SKILL.md +11 -0
- package/skills/data360-orchestrate/SKILL.md +30 -0
- package/skills/data360-prepare/SKILL.md +14 -0
- package/skills/data360-query/SKILL.md +10 -0
- package/skills/data360-schema-get/SKILL.md +7 -0
- package/skills/data360-segment/SKILL.md +11 -0
- package/skills/design-systems-slds-validate/SKILL.md +8 -0
- package/skills/design-systems-slds2-migrate/SKILL.md +3 -0
- package/skills/dx-apexguru-scan/SKILL.md +403 -0
- package/skills/dx-apexguru-scan/examples/README.md +54 -0
- package/skills/dx-apexguru-scan/examples/sample-decoded-summary.json +176 -0
- package/skills/dx-apexguru-scan/examples/sample-full-no-runtime-response.json +26 -0
- package/skills/dx-apexguru-scan/examples/sample-succeeded-response.json +15 -0
- package/skills/dx-apexguru-scan/references/api-reference.md +81 -0
- package/skills/dx-apexguru-scan/references/authentication.md +134 -0
- package/skills/dx-apexguru-scan/references/error-handling.md +56 -0
- package/skills/dx-apexguru-scan/references/violation-catalog.md +28 -0
- package/skills/dx-apexguru-scan/scripts/build-zip.sh +87 -0
- package/skills/dx-apexguru-scan/scripts/decode-report.js +389 -0
- package/skills/dx-apexguru-scan/scripts/resolve-token.sh +151 -0
- package/skills/dx-apexguru-scan/scripts/run-scan.sh +153 -0
- package/skills/dx-apexguru-scan/scripts/scan.sh +96 -0
- package/skills/dx-apexguru-scan/scripts/validate-token.js +121 -0
- package/skills/dx-app-analytics-query/SKILL.md +5 -0
- package/skills/dx-code-analyzer-configure/SKILL.md +5 -5
- package/skills/dx-code-analyzer-custom-rule-create/SKILL.md +3 -1
- package/skills/dx-code-analyzer-run/SKILL.md +10 -2
- package/skills/dx-devops-pipeline-manage/SKILL.md +263 -0
- package/skills/dx-devops-pipeline-manage/examples/common-workflows.md +177 -0
- package/skills/dx-devops-pipeline-manage/references/cli-commands.md +298 -0
- package/skills/dx-devops-pipeline-manage/references/parsing-patterns.md +134 -0
- package/skills/dx-devops-pipeline-manage/scripts/check-activation-ready.sh +34 -0
- package/skills/dx-devops-pipeline-manage/scripts/validate-org-type.sh +17 -0
- package/skills/dx-devops-pipeline-manage/scripts/verify-operation.sh +82 -0
- package/skills/dx-devops-promote/SKILL.md +214 -0
- package/skills/dx-devops-promote/examples/promotion-workflows.md +212 -0
- package/skills/dx-devops-promote/references/cli-commands.md +303 -0
- package/skills/dx-devops-test-failures-analyze/SKILL.md +8 -0
- package/skills/dx-devops-test-pipeline-configure/SKILL.md +7 -0
- package/skills/dx-devops-test-suite-assignments-configure/SKILL.md +9 -0
- package/skills/dx-devops-test-suite-run/SKILL.md +8 -0
- package/skills/dx-org-switch/SKILL.md +3 -0
- package/skills/experience-lwc-base-components-integrate/SKILL.md +176 -0
- package/skills/experience-lwc-base-components-integrate/references/lbc-expert-guidance.md +127 -0
- package/skills/experience-lwc-base-components-integrate/references/lightning-component-index.md +179 -0
- package/skills/experience-lwc-base-components-integrate/references/lightning-components.md +5429 -0
- package/skills/experience-lwc-base-components-integrate/scripts/extract-component-docs.sh +61 -0
- package/skills/experience-lwc-generate/SKILL.md +18 -0
- package/skills/experience-lwc-rtl-validate/SKILL.md +149 -0
- package/skills/experience-lwc-rtl-validate/references/rtl-expert.md +892 -0
- package/skills/experience-lwc-rtl-validate/scripts/scan-rtl-css.sh +206 -0
- package/skills/experience-lwc-typescript-migrate/SKILL.md +207 -0
- package/skills/experience-lwc-typescript-migrate/assets/dts-template.ts +15 -0
- package/skills/experience-lwc-typescript-migrate/assets/type-patterns.ts +44 -0
- package/skills/experience-lwc-typescript-migrate/scripts/find-consumers.sh +128 -0
- package/skills/experience-lwr-site-generate/SKILL.md +1 -1
- package/skills/experience-ui-bundle-agentforce-client-generate/SKILL.md +5 -2
- package/skills/experience-ui-bundle-custom-app-generate/SKILL.md +1 -1
- package/skills/experience-ui-bundle-file-upload-generate/SKILL.md +5 -0
- package/skills/experience-ui-bundle-localize/SKILL.md +323 -0
- package/skills/experience-ui-bundle-localize/references/gotchas.md +249 -0
- package/skills/experience-ui-bundle-localize/references/i18n-setup.md +169 -0
- package/skills/experience-ui-bundle-localize/references/interpolation.md +311 -0
- package/skills/experience-ui-bundle-localize/references/label-xml.md +282 -0
- package/skills/experience-ui-bundle-localize/references/verifying.md +219 -0
- package/skills/experience-ui-bundle-localize/scripts/check-i18n-wired.sh +195 -0
- package/skills/experience-ui-bundle-localize/scripts/check-manifest-registered.sh +100 -0
- package/skills/experience-ui-bundle-localize/scripts/check-org-api-version.sh +40 -0
- package/skills/experience-ui-bundle-localize/scripts/detect-bundle-type.sh +57 -0
- package/skills/experience-ui-bundle-metadata-generate/SKILL.md +1 -1
- package/skills/experience-ui-bundle-project-generate/SKILL.md +4 -4
- package/skills/experience-ui-bundle-salesforce-data-access/SKILL.md +11 -0
- package/skills/external-diagram-mermaid-generate/SKILL.md +21 -0
- package/skills/integration-connectivity-generate/SKILL.md +17 -0
- package/skills/integration-eventing-cdc-configure/SKILL.md +9 -0
- package/skills/integration-eventing-subscription-configure/SKILL.md +7 -0
- package/skills/mobile-apps-create/SKILL.md +5 -0
- package/skills/mobile-platform-native-capabilities-integrate/SKILL.md +3 -0
- package/skills/mobile-platform-offline-validate/SKILL.md +9 -0
- package/skills/omnistudio-callable-apex-generate/SKILL.md +14 -0
- package/skills/omnistudio-datamapper-generate/SKILL.md +13 -0
- package/skills/omnistudio-datapacks-deploy/SKILL.md +18 -0
- package/skills/omnistudio-dependencies-analyze/SKILL.md +12 -0
- package/skills/omnistudio-epc-catalog-generate/SKILL.md +15 -0
- package/skills/omnistudio-flexcard-generate/SKILL.md +11 -0
- package/skills/omnistudio-integration-procedure-generate/SKILL.md +11 -0
- package/skills/omnistudio-omniscript-generate/SKILL.md +9 -0
- package/skills/platform-agentexchange-partner-offers-configure/SKILL.md +8 -0
- package/skills/platform-agentsetup-categories-fetch/SKILL.md +3 -0
- package/skills/platform-apex-generate/SKILL.md +5 -0
- package/skills/platform-apex-logs-debug/SKILL.md +12 -0
- package/skills/platform-apex-test-generate/SKILL.md +5 -0
- package/skills/platform-apex-test-run/SKILL.md +14 -0
- package/skills/platform-custom-application-generate/SKILL.md +1 -0
- package/skills/platform-custom-field-generate/SKILL.md +1 -1
- package/skills/platform-custom-lightning-type-generate/SKILL.md +3 -0
- package/skills/platform-custom-lightning-type-generate/assets/primitive-types-and-constraints.md +1 -1
- package/skills/platform-custom-tab-generate/SKILL.md +1 -0
- package/skills/platform-data-manage/SKILL.md +15 -0
- package/skills/platform-dataspace-access-configure/SKILL.md +2 -2
- package/skills/platform-flexipage-generate/SKILL.md +3 -0
- package/skills/platform-lightning-app-coordinate/SKILL.md +18 -1
- package/skills/platform-mcp-tool-widget-coordinate/SKILL.md +250 -0
- package/skills/platform-mcp-tool-widget-coordinate/examples/action-name-source-prompt.md +74 -0
- package/skills/platform-mcp-tool-widget-coordinate/examples/apex-invocable-source-prompt.md +90 -0
- package/skills/platform-mcp-tool-widget-coordinate/examples/nested-object-source-prompt.md +191 -0
- package/skills/platform-mcp-tool-widget-coordinate/examples/pasted-tool-output-prompt.md +85 -0
- package/skills/platform-mcp-tool-widget-coordinate/references/build-plan-format.md +74 -0
- package/skills/platform-mcp-tool-widget-coordinate/references/mcp-tool-output-discovery.md +184 -0
- package/skills/platform-mcp-tool-widget-coordinate/references/two-clt-modeling.md +128 -0
- package/skills/platform-mcp-tool-widget-coordinate/references/validation-gates.md +181 -0
- package/skills/platform-metadata-api-context-get/SKILL.md +6 -2
- package/skills/platform-metadata-retrieve/SKILL.md +5 -0
- package/skills/platform-models-api-configure/SKILL.md +10 -0
- package/skills/platform-permission-set-generate/SKILL.md +1 -2
- package/skills/platform-policy-rule-generate/SKILL.md +2 -0
- package/skills/platform-report-generate/SKILL.md +1 -1
- package/skills/platform-sharing-rules-generate/SKILL.md +1 -1
- package/skills/platform-soql-query/SKILL.md +13 -0
- package/skills/platform-tracing-agentforce-configure/SKILL.md +5 -1
- package/skills/platform-tracing-configure/SKILL.md +4 -1
- package/skills/platform-trust-archive-manage/SKILL.md +3 -0
- package/skills/platform-validation-rule-generate/SKILL.md +1 -0
- package/skills/platform-widget-generate/SKILL.md +2 -1
- package/skills/sales-agentforce-pipeline-management-configure/SKILL.md +3 -1
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# MCP Tool Output Discovery
|
|
2
|
+
|
|
3
|
+
Phase 2 resolves the payload shape that defines the response CLT and the widget schema. There are three sources, in order of preference: an invocable action API name (`action`), a pasted tool-output sample (`sample`), or an Apex Invocable class (`apex`).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
| Source | Use when | Authority |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `action` | An **invocable action API name** is known — directly, or from a class name that resolves to one. **Preferred.** | The org's Actions REST API describes the action's typed outputs directly — it already excludes the request wrapper and private helpers. |
|
|
10
|
+
| `sample` | The describe 404s or no org is reachable, but a pasted tool-output JSON is available. | Infers types from example values. |
|
|
11
|
+
| `apex` | Only the Apex **class** name is known, and no org and no sample are available — fallback only, may be stale relative to what's deployed. | Parses `@InvocableVariable` fields from source. |
|
|
12
|
+
|
|
13
|
+
Prefer `action` whenever an action name (directly given, or derived from a class name that resolves to a single invocable action) and an authenticated org are available — it is the same schema the platform itself exposes, so it needs no request/helper filtering and gives real field types. Fall back to `sample`, then `apex`.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## `action` — resolve from the invocable action name (preferred)
|
|
18
|
+
|
|
19
|
+
The Salesforce **Actions REST API** describes any custom Apex invocable action, including its output variables and their types. This is authoritative: the `outputs` it returns are exactly the `@InvocableVariable` fields on the response class — the request wrapper and private helper classes never appear.
|
|
20
|
+
|
|
21
|
+
### 1. Confirm the action API name
|
|
22
|
+
|
|
23
|
+
For an Apex invocable action the action API name is the **Apex class name** that declares the `@InvocableMethod` (e.g. `GetAccountSummaryTest`), not the method label. If the user gave a label ("Get Account Summary") resolve it to the class name — the class name is what the endpoint path uses.
|
|
24
|
+
|
|
25
|
+
### 2. Describe the action
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
sf api request rest '/services/data/v63.0/actions/custom/apex/<ActionApiName>' -o <org>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`<ActionApiName>` is the Apex class name. Use the org's API version (`v63.0` here — match `sourceApiVersion` in `sfdx-project.json` or the org's max). If the org alias is the default, `-o <org>` may be omitted. (`sf api request rest ...` is the form used elsewhere in this repo; `sf org api request rest ...` is an equivalent alias.)
|
|
32
|
+
|
|
33
|
+
To list all custom Apex actions first (when the exact name is unknown) — the action names are under `.actions[].name`:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
sf api request rest '/services/data/v63.0/actions/custom/apex' -o <org> | jq -r '.actions[].name'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
If the describe returns 404 / `NOT_FOUND`, the action is not deployed or is not exposed as a custom Apex action — fall back to `sample` (a pasted tool-output JSON) if one is available, else `apex` (parse the class), and surface the miss.
|
|
40
|
+
|
|
41
|
+
### 3. Read the `outputs` array
|
|
42
|
+
|
|
43
|
+
The describe response has an `outputs` array. Each entry describes one payload field:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"outputs": [
|
|
48
|
+
{ "name": "accountName", "label": "Account Name", "type": "STRING", "maxOccurs": 1 },
|
|
49
|
+
{ "name": "contactCount", "label": "Contact Count", "type": "INTEGER", "maxOccurs": 1 },
|
|
50
|
+
{ "name": "totalOpportunityAmount", "label": "Total Opportunity Amount", "type": "DOUBLE", "maxOccurs": 1 }
|
|
51
|
+
],
|
|
52
|
+
"inputs": [ { "name": "accountId", "type": "ID", "required": true } ]
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
- **Use `outputs` only.** `inputs` is the tool input (the request wrapper) — exclude it, exactly as `apex` excludes the request class.
|
|
57
|
+
- `name` → the CLT/widget property key. `label` → the property `title`.
|
|
58
|
+
- A field with `maxOccurs > 1` is a **collection** (list). For the beta, surface it to the user in the build plan — the widget renders a single response, and list payloads need a nested item CLT (out of scope for the default flow).
|
|
59
|
+
- An entry with **`"type": null` and an `"apexClass"` key instead** (e.g. `{ "name": "flightInfo", "type": null, "apexClass": "SearchFlightsAction$Flight", "maxOccurs": 1 }`) is **not missing data to default to text** — it is the describe's encoding for a field typed as another Apex class. `$` separates the outer class from the inner class, matching the `@apexClassType/<ns>__<OuterClass>$<InnerClass>` convention used elsewhere in this skill. This is the same case as a `List<ApexClass>`/nested-object field from the other two sources — see "Nested-object payload fields" below; the Actions REST API describe never exposes that class's own leaf fields, so retrieving/reading the Apex class named in `apexClass` (via `apex` §1/§3) is the correct next step, not a fallback away from `action`.
|
|
60
|
+
|
|
61
|
+
Extract the field list with `jq` (do NOT wrap in `$()`):
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
sf api request rest '/services/data/v63.0/actions/custom/apex/<ActionApiName>' -o <org> \
|
|
65
|
+
| jq -r '.outputs[] | "\(.name)\t\(.type)"'
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 4. Map Actions-API `type` → CLT `lightning:type`
|
|
69
|
+
|
|
70
|
+
| Actions API `type` | CLT `lightning:type` |
|
|
71
|
+
|---|---|
|
|
72
|
+
| `STRING`, `TEXTAREA`, `PICKLIST`, `ID`, `REFERENCE`, `EMAIL`, `PHONE`, `URL` | `lightning__textType` |
|
|
73
|
+
| `INTEGER`, `INT`, `LONG` | `lightning__integerType` |
|
|
74
|
+
| `DOUBLE`, `DECIMAL`, `CURRENCY`, `PERCENT` | `lightning__numberType` |
|
|
75
|
+
| `BOOLEAN` | `lightning__booleanType` |
|
|
76
|
+
| `DATE` | `lightning__dateType` |
|
|
77
|
+
| `DATETIME` | `lightning__dateTimeType` |
|
|
78
|
+
|
|
79
|
+
Casing varies by API version (some return `Int`/`Double`, some `INTEGER`/`DOUBLE`) — match case-insensitively. An unrecognized `type` defaults to `lightning__textType`; note the assumption in the build plan.
|
|
80
|
+
|
|
81
|
+
> **Widget schema vs CLT schema type vocabulary** (applies to every source). The response CLT uses `lightning__integerType` for integers. The widget `schema.json` (per `platform-widget-generate`) has no integer type — all numerics are `lightning__numberType`. So integer fields are `lightning__integerType` in the *response CLT* but `lightning__numberType` in the *widget* schema. Do not copy CLT leaf types verbatim into the widget schema. Renderer bindings are strings and type-agnostic.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## `sample` — parse from a pasted tool-output JSON (fallback)
|
|
86
|
+
|
|
87
|
+
Use when the action describe 404s or no org is reachable, but a pasted tool-output sample is available.
|
|
88
|
+
|
|
89
|
+
Given a pasted envelope sample, read the `outputValues` object and infer each field's type from its value:
|
|
90
|
+
|
|
91
|
+
| JSON value | CLT `lightning:type` |
|
|
92
|
+
|---|---|
|
|
93
|
+
| string | `lightning__textType` |
|
|
94
|
+
| integer (no fraction) | `lightning__integerType` |
|
|
95
|
+
| number (fractional) | `lightning__numberType` |
|
|
96
|
+
| boolean | `lightning__booleanType` |
|
|
97
|
+
|
|
98
|
+
Confirm the envelope keys (`actionName`, `isSuccess`, `outputValues`) against the sample. If the sample nests the payload further (e.g. `outputValues.data.<field>`), the response CLT and the renderer bindings must reflect that extra level (`{!$attrs.outputValues.data.<field>}`) — surface this in the build plan, because it changes every binding.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## `apex` — parse the Invocable class (fallback)
|
|
103
|
+
|
|
104
|
+
Use when no org is reachable and no sample is available, but the `.cls` is in the project.
|
|
105
|
+
|
|
106
|
+
### 1. Locate the class
|
|
107
|
+
|
|
108
|
+
Search the local project first: `<pkgDir>/classes/<ClassName>.cls` where `<pkgDir>` = `<packageDirectories[].path>/main/default`. If absent, retrieve from the org:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
sf project retrieve start --metadata ApexClass:<ClassName>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
If it exists nowhere, STOP and surface — the payload shape cannot be enumerated.
|
|
115
|
+
|
|
116
|
+
### 2. Identify the response class
|
|
117
|
+
|
|
118
|
+
The Invocable method is annotated `@InvocableMethod` and returns `List<ResponseType>`. The **response class** is that element type.
|
|
119
|
+
|
|
120
|
+
```apex
|
|
121
|
+
@InvocableMethod(label='Get Account Summary')
|
|
122
|
+
global static List<GetAccountSummaryResponse> getAccountSummary(
|
|
123
|
+
List<GetAccountSummaryRequest> requests
|
|
124
|
+
) { ... }
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
- Response class = `GetAccountSummaryResponse` (the `List<...>` element type). **This is the payload source.**
|
|
128
|
+
- Request class = `GetAccountSummaryRequest` (the parameter element type). **Excluded** — it is the tool input, not output.
|
|
129
|
+
- Private helper classes (e.g. `private class OpportunityMetrics`) are **excluded** — not part of the invocable's externally visible schema. The Apex author signals this with `private`; respect it.
|
|
130
|
+
|
|
131
|
+
### 3. Enumerate `@InvocableVariable` fields
|
|
132
|
+
|
|
133
|
+
Read the response class block and list every field annotated `@InvocableVariable`. These become the response CLT `properties` and the widget schema properties (1:1).
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Print the response class field declarations. Do NOT wrap in $().
|
|
137
|
+
echo "INVOCABLE_FIELDS:"
|
|
138
|
+
grep -A1 '@InvocableVariable' <pkgDir>/classes/<ClassName>.cls \
|
|
139
|
+
| grep -oE '(public|global)\s+[A-Za-z0-9_<>,\s]+\s+[a-zA-Z_][a-zA-Z0-9_]*\s*;' \
|
|
140
|
+
| sed -E 's/.*\s([a-zA-Z_][a-zA-Z0-9_]*)\s*;/\1/' \
|
|
141
|
+
| sort -u
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
If the grep misses multi-line annotations, read the `.cls` with the Read tool and list fields manually — but do not skip enumeration. Scope the enumeration to the **response class block only**; do not pick up `@InvocableVariable` fields from the request class.
|
|
145
|
+
|
|
146
|
+
### 4. Map Apex → CLT `lightning:type`
|
|
147
|
+
|
|
148
|
+
| Apex type | CLT `lightning:type` |
|
|
149
|
+
|---|---|
|
|
150
|
+
| `String`, `Id` | `lightning__textType` |
|
|
151
|
+
| `Integer`, `Long` | `lightning__integerType` |
|
|
152
|
+
| `Decimal`, `Double` | `lightning__numberType` |
|
|
153
|
+
| `Boolean` | `lightning__booleanType` |
|
|
154
|
+
| `Date` | `lightning__dateType` |
|
|
155
|
+
| `Datetime` | `lightning__dateTimeType` |
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Nested-object payload fields (applies to every source above)
|
|
160
|
+
|
|
161
|
+
The mapping tables above (Actions-API `type`, Apex type, JSON value/schema `type`) cover **primitive** fields. A field can also be typed as **another Apex class** instead of a primitive — e.g. `GetFlightDetailsAction.FlightDetailsResponse.flightInfo`, typed `SearchFlightsAction.Flight`. This is a second, additive branch — check every payload field against it, regardless of which of the three sources produced the field list:
|
|
162
|
+
|
|
163
|
+
- **Actions API**: an output entry with `"type": null` and an `"apexClass": "<OuterClass>$<InnerClass>"` key, rather than a primitive `STRING`/`INTEGER`/etc. `type` (see step 3 above).
|
|
164
|
+
- **`apex`**: an `@InvocableVariable` field whose declared type is not `String`/`Id`/`Integer`/`Long`/`Decimal`/`Double`/`Boolean`/`Date`/`Datetime` but another Apex class.
|
|
165
|
+
- **`sample`**: a property whose JSON value/schema `type` is `"object"` (not a primitive).
|
|
166
|
+
|
|
167
|
+
**Never** model such a field as `{"type":"object"}` (opaque, unrenderable) or inline it as a nested `lightning__objectType` (rejected by the CLT metaschema — same rule as the envelope↔response relationship). Instead:
|
|
168
|
+
|
|
169
|
+
1. Type the response CLT property as `"@apexClassType/<ns>__<OuterClass>$<InnerClass>"` (e.g. `"@apexClassType/c__SearchFlightsAction$Flight"`) — the same convention `platform-custom-lightning-type-generate` documents for Apex-backed CLTs.
|
|
170
|
+
2. Enumerate the referenced Apex class's own fields (its own `@InvocableVariable`/public members) — these become the widget's leaf properties. The object field itself never appears on the widget.
|
|
171
|
+
3. Bind the renderer one level deeper: `{!$attrs.outputValues.<objectField>.<leaf>}` (e.g. `{!$attrs.outputValues.flightInfo.flightId}`), not `{!$attrs.outputValues.<objectField>}`.
|
|
172
|
+
4. A field typed `List<ApexClass>` (a list of nested objects, not a single one) is out of scope for the beta single-response flow — surface it in the build plan like a `maxOccurs > 1` scalar rather than emitting a schema for it.
|
|
173
|
+
|
|
174
|
+
See `references/two-clt-modeling.md` ("Nested-object payload fields") for the worked JSON, and `examples/nested-object-source-prompt.md` for the full end-to-end walkthrough.
|
|
175
|
+
|
|
176
|
+
## Output of Phase 2
|
|
177
|
+
|
|
178
|
+
`payloadFields` — an ordered list of `{ name, title, lightning:type }` describing the response payload (primitive fields), plus any nested-object fields resolved to `@apexClassType/...` per above. This drives:
|
|
179
|
+
|
|
180
|
+
- the **response CLT** `properties` (CLT type vocabulary, `lightning__integerType` allowed, `@apexClassType/...` for nested-object fields),
|
|
181
|
+
- the **widget schema** `properties.attributes.properties` (widget type vocabulary, numerics → `lightning__numberType`; nested-object fields flattened to their leaf properties),
|
|
182
|
+
- the **renderer** attribute bindings (`{!$attrs.outputValues.<name>}` for primitives, `{!$attrs.outputValues.<objectField>.<leaf>}` for nested-object leaves).
|
|
183
|
+
|
|
184
|
+
Whichever source produced the fields, record it in the build plan so the reviewer knows whether the schema came from the live org (`action`), source (`apex`), or an example (`sample`).
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Two-CLT Modeling for an MCP Tool Output
|
|
2
|
+
|
|
3
|
+
A custom MCP server tool backed by an Apex Invocable Action returns the platform's **invocable-action result envelope**. The real payload the tool consumer cares about lives under `outputValues`; the surrounding fields (`actionName`, `isSuccess`, `errors`, `sortOrder`, `version`, …) are envelope metadata.
|
|
4
|
+
|
|
5
|
+
To render this with an HXL widget we model it as **two object-based CLTs** and wire them with a renderer that bridges the nesting. Both are ordinary CLTs of equal standing — nothing in the platform or the metaschema distinguishes an "envelope type" from a "response type." The only reason two files exist is that one CLT (the envelope) must reference the other (the response) by name via `c__<name>`, and a CLT cannot reference itself — so the two need distinct deployed names, nothing more. Don't invent a role-label pair for the two CLTs themselves ("Payload CLT"/"Envelope CLT", "Outer CLT"/"Inner CLT") — name and describe each by what it actually models (see below), and in prose refer to them by that same identifier: "the `<toolApiName>` envelope" / "the `<toolApiName>Response`". ("Payload" and "response" remain fine as ordinary words for the data itself — e.g. "response fields", "the payload the tool consumer cares about" — the rule is about not naming or labeling the *CLTs* by an invented role.)
|
|
6
|
+
|
|
7
|
+
## Naming convention
|
|
8
|
+
|
|
9
|
+
| Artifact | Convention | Example |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| Envelope CLT | `<toolApiName>` | `getFlightDetails` |
|
|
12
|
+
| Response CLT | `<toolApiName>Response` | `getFlightDetailsResponse` |
|
|
13
|
+
| Widget | `<toolApiName>Widget` | `getFlightDetailsWidget` |
|
|
14
|
+
|
|
15
|
+
- `<toolApiName>` is derived **deterministically from the Apex class / Invocable Action name**, not the label: lower-camelCase the class name and strip a trailing `Action`, `Test`, or `WidgetAction` suffix if present.
|
|
16
|
+
- `AccountSummaryWidgetAction` → `accountSummary`
|
|
17
|
+
- `GetFlightDetailsAction` → `getFlightDetails`
|
|
18
|
+
- `GetAccountSummaryTest` → `getAccountSummary`
|
|
19
|
+
- Only when no class/action name is available at all (e.g. a bare `sample` with no `actionName` resolvable to a class) fall back to camelCasing the tool/action **label** (e.g. `Get Account Summary` → `accountSummary`).
|
|
20
|
+
- Both CLT names are derived from the **same single `<toolApiName>`** — there is no separate naming decision to make per artifact, and no free-standing role word (no "Result", "OutputValues", "Payload", "Envelope", and no `_CLT` suffix either — a Lightning Type is identified by living under `lightningTypes/`, not by a suffix on its name). `Response` is not a role label; it is literally what the class is (the Invocable Action's declared `List<...Response>` return-element type) — the same word the Apex source itself already uses (e.g. `GetAccountSummaryResponse`, `FlightDetailsResponse`).
|
|
21
|
+
- The envelope CLT is *structurally* generic but **cannot be a single shared CLT** — its `outputValues` must be typed to a tool-specific response CLT via `c__<responseCLT>`. One envelope CLT per tool.
|
|
22
|
+
|
|
23
|
+
> **Naming convention supersedes the earlier hand-verified prototype.** Two bundles were manually fixed and successfully deployed during development using an older `<toolApiName>Result` / `<toolApiName>OutputValues` naming pair — that proved the *structural* pattern (two object-based CLTs, `@apexClassType` for nested fields, two-level renderer bindings) deploys correctly. The naming convention above replaces those two suffixes; every other structural rule in this file (root keys, `unevaluatedProperties`, the `c__` reference, nested-object typing, renderer bindings) is unchanged and still matches what was verified.
|
|
24
|
+
|
|
25
|
+
## Response CLT
|
|
26
|
+
|
|
27
|
+
Object-based CLT whose `properties` are exactly the response `@InvocableVariable` fields (1:1). Root `lightning:type` is `lightning__objectType`. `platform-custom-lightning-type-generate` injects and enforces `"unevaluatedProperties": false` on every object-based CLT (its metaschema rejects a CLT without it) — this orchestrator does not fight that, it matches it in every example and every generated file. Give both CLTs a real, tool-specific `description` (never `""`) — it is what a consumer sees when picking a referenced CLT. Both CLTs also carry a root-level `"lightning:tags": ["mcp"]` — it marks the type as MCP-tool-generated per `platform-custom-lightning-type-generate/assets/primitive-types-and-constraints.md`.
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"title": "Get Account Summary Response",
|
|
32
|
+
"description": "Response fields from the GetAccountSummaryTest invocable-action (GetAccountSummaryResponse)",
|
|
33
|
+
"type": "object",
|
|
34
|
+
"lightning:type": "lightning__objectType",
|
|
35
|
+
"lightning:tags": ["mcp"],
|
|
36
|
+
"unevaluatedProperties": false,
|
|
37
|
+
"properties": {
|
|
38
|
+
"accountName": { "title": "accountName", "lightning:type": "lightning__textType" },
|
|
39
|
+
"accountIndustry":{ "title": "accountIndustry","lightning:type": "lightning__textType" },
|
|
40
|
+
"contactCount": { "title": "contactCount", "lightning:type": "lightning__integerType" },
|
|
41
|
+
"totalOpportunityAmount": { "title": "totalOpportunityAmount", "lightning:type": "lightning__numberType" }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Nested-object payload fields (a second, additive case)
|
|
47
|
+
|
|
48
|
+
The example above covers a **flat** payload — every `@InvocableVariable` field is a primitive. Some invocable responses instead have a field whose type is **itself an Apex class** (e.g. `GetFlightDetailsAction.FlightDetailsResponse.flightInfo`, typed `SearchFlightsAction.Flight`). Both shapes are in scope; pick the branch per field:
|
|
49
|
+
|
|
50
|
+
- **Never** type that property as a bare `{"type":"object"}` (opaque, unrenderable, and not what deploys) and **never** inline it as a nested `lightning__objectType` (rejected by the CLT metaschema, same as the envelope↔response relationship below).
|
|
51
|
+
- **Do** type it as `"@apexClassType/<ns>__<OuterClass>$<InnerClass>"` — e.g. `"lightning:type": "@apexClassType/c__SearchFlightsAction$Flight"` — exactly the Apex-backed-CLT convention `platform-custom-lightning-type-generate` already documents for `@apexClassType/namespace__ClassName$InnerClass`.
|
|
52
|
+
- The **widget** and **renderer** then flatten through it — see the nested-binding note at the end of the "Default renderer" section below, and the full walkthrough in `examples/nested-object-source-prompt.md`.
|
|
53
|
+
- A field typed `List<ApexClass>` (a list of nested objects) is out of scope for the beta single-response flow — surface it in the build plan rather than emitting a schema for it, the same way a `maxOccurs > 1` scalar is surfaced.
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"title": "Get Flight Details Response",
|
|
58
|
+
"description": "Response fields from the GetFlightDetailsAction invocable-action (FlightDetailsResponse)",
|
|
59
|
+
"type": "object",
|
|
60
|
+
"lightning:type": "lightning__objectType",
|
|
61
|
+
"lightning:tags": ["mcp"],
|
|
62
|
+
"unevaluatedProperties": false,
|
|
63
|
+
"properties": {
|
|
64
|
+
"flightInfo": {
|
|
65
|
+
"title": "Flight Info",
|
|
66
|
+
"lightning:type": "@apexClassType/c__SearchFlightsAction$Flight"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Envelope CLT
|
|
73
|
+
|
|
74
|
+
Object-based CLT that mimics the tool-result envelope. `outputValues` is typed to the response CLT via the referenced-CLT pattern `c__<responseCLT>` — **not** inlined as a nested `lightning__objectType` (nested object typing is rejected by the CLT metaschema; see `platform-custom-lightning-type-generate`).
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"title": "Get Account Summary",
|
|
79
|
+
"description": "Invocable-action result envelope for the GetAccountSummaryTest MCP tool",
|
|
80
|
+
"type": "object",
|
|
81
|
+
"lightning:type": "lightning__objectType",
|
|
82
|
+
"lightning:tags": ["mcp"],
|
|
83
|
+
"unevaluatedProperties": false,
|
|
84
|
+
"properties": {
|
|
85
|
+
"actionName": { "title": "actionName", "lightning:type": "lightning__textType" },
|
|
86
|
+
"isSuccess": { "title": "isSuccess", "lightning:type": "lightning__booleanType" },
|
|
87
|
+
"outputValues": { "title": "outputValues", "lightning:type": "c__getAccountSummaryResponse" }
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
- The `c__<responseCLT>` string is the referenced type's **registered identifier / FQN**, not its `title`. It must match the response CLT's deployed name.
|
|
93
|
+
- The response CLT must be deployed **before** the envelope CLT.
|
|
94
|
+
- Include only the envelope scalars the widget or the platform needs (`actionName`, `isSuccess`, and `outputValues` at minimum). Add `message` etc. only when rendered.
|
|
95
|
+
|
|
96
|
+
## Default renderer (in the ENVELOPE CLT)
|
|
97
|
+
|
|
98
|
+
The renderer is the **default `renderer.json` at the envelope CLT bundle root**, parallel to `schema.json` — NOT under `lightningDesktopGenAi/`. It assigns the widget and bridges the envelope nesting to the flat widget schema.
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"renderer": {
|
|
103
|
+
"componentOverrides": {
|
|
104
|
+
"$": {
|
|
105
|
+
"definition": "@widget/c/accountSummaryWidget",
|
|
106
|
+
"attributes": {
|
|
107
|
+
"accountName": "{!$attrs.outputValues.accountName}",
|
|
108
|
+
"accountIndustry":"{!$attrs.outputValues.accountIndustry}",
|
|
109
|
+
"contactCount": "{!$attrs.outputValues.contactCount}",
|
|
110
|
+
"totalOpportunityAmount": "{!$attrs.outputValues.totalOpportunityAmount}"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**The binding path is the crux:** each widget attribute (left, flat) maps to the response field nested under the envelope's `outputValues` node (right) via `{!$attrs.outputValues.<field>}`. Because the envelope CLT's `outputValues` is typed to the response CLT, the runtime can resolve `outputValues.<field>` against the response CLT's `properties`.
|
|
119
|
+
|
|
120
|
+
**Nested-object response fields bind one level deeper.** When a response field is itself an Apex-class reference (the `flightInfo` case above), the widget flattens to that class's own leaf fields, and the renderer binding goes two levels deep: `{!$attrs.outputValues.flightInfo.flightId}`, `{!$attrs.outputValues.flightInfo.origin}`, etc. — `outputValues.<objectField>.<leaf>`, not `outputValues.<objectField>` alone (which would bind the widget to an unresolvable object, not a renderable leaf).
|
|
121
|
+
|
|
122
|
+
## Why two CLTs and not one
|
|
123
|
+
|
|
124
|
+
The platform binds the tool's output rendition to the CLT whose shape matches the **tool output schema** — that is the envelope, not the response. So the renderer (and thus the widget assignment) must live in the envelope CLT. But the widget wants a flat attribute contract, so the renderer flattens the nesting via `outputValues.`. The response CLT exists purely to *type* the `outputValues` node so those nested paths resolve. Inlining the response fields as a nested `lightning__objectType` inside the envelope is rejected by the CLT metaschema — hence a separate, referenced response CLT.
|
|
125
|
+
|
|
126
|
+
## The widget schema is generic, not CLT-derived
|
|
127
|
+
|
|
128
|
+
The widget schema is a standalone contract: `properties.attributes.properties` built from the **response field list** (name + primitive `lightning:type`), nothing more. It happens to share the field set with the response CLT for this flow, but it is not typed against the CLT, does not carry `unevaluatedProperties`, and would look identical if the same field list arrived from any other source `platform-widget-generate` supports. The widget schema and body know nothing about the envelope. The widget binds `{!$attrs.accountName}` (flat); only the renderer knows the field actually lives at `outputValues.accountName`. This keeps the widget reusable and lets `platform-widget-generate` author it exactly as it would for any flat response.
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Validation Gates
|
|
2
|
+
|
|
3
|
+
The orchestrator runs only **cross-skill validations** — checks that span the two CLTs, the widget, and the renderer. Widget-bundle-internal checks (schema parses, root keys, leaf types, `{!$attrs.X}` resolution, `.uiwidget-meta.xml` well-formedness, `<UiWidgetBundle>` root, widget-type) are owned by `platform-widget-generate` and run in its own self-validation.
|
|
4
|
+
|
|
5
|
+
Run every gate below. If a hard gate fails, fix and re-run before reporting success. Warn gates are advisory.
|
|
6
|
+
|
|
7
|
+
**Shell note:** run each command verbatim and reason about its printed output. Do NOT capture into shell variables with `$(…)`, do NOT use process substitution `<(…)`, do NOT use brace expansion. Vibes' safe-shell filter blocks those patterns and prompts for manual approval even in Bypass mode. See Hard Rule 11 in the SKILL.md.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Hard — block on failure
|
|
12
|
+
|
|
13
|
+
### 1. `clt-reference-integrity`
|
|
14
|
+
|
|
15
|
+
Confirms the envelope→response typing the renderer depends on.
|
|
16
|
+
|
|
17
|
+
1. **Both CLTs parse:**
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
jq . <pkgDir>/lightningTypes/<responseCLT>/schema.json > /dev/null && echo "RESPONSE_PARSE: ok" || echo "RESPONSE_PARSE: FAIL"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
jq . <pkgDir>/lightningTypes/<toolCLT>/schema.json > /dev/null && echo "ENVELOPE_PARSE: ok" || echo "ENVELOPE_PARSE: FAIL"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
2. **Envelope `outputValues` references the response CLT.** Print the value and compare in reasoning:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
jq -r '.properties.outputValues["lightning:type"]' <pkgDir>/lightningTypes/<toolCLT>/schema.json
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Expected: `c__<responseCLT>`. Match → `REFERENCE: ok`; else `REFERENCE: FAIL (got <actual>, expected c__<responseCLT>)`.
|
|
34
|
+
|
|
35
|
+
3. **Neither CLT carries a forbidden keyword.** Print any hits (empty output = clean):
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
jq 'paths | select(.[-1] == "$schema" or .[-1] == "items")' <pkgDir>/lightningTypes/<responseCLT>/schema.json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
jq 'paths | select(.[-1] == "$schema" or .[-1] == "items")' <pkgDir>/lightningTypes/<toolCLT>/schema.json
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Any output → `KEYWORDS: FAIL (<path>)`; empty → `KEYWORDS: ok`.
|
|
46
|
+
|
|
47
|
+
4. **Nested-object response fields (if any) use `@apexClassType`, never a bare object.** For every response CLT property that is not a primitive leaf, print its `lightning:type`:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
jq -r '.properties | to_entries[] | select(.value["lightning:type"] == null or (.value["lightning:type"] | test("^lightning__") | not)) | "\(.key): \(.value["lightning:type"])"' <pkgDir>/lightningTypes/<responseCLT>/schema.json
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Every printed entry must match `@apexClassType/<ns>__<OuterClass>$<InnerClass>`. A bare `{"type":"object"}` (no `lightning:type`, or a `lightning:type` of `lightning__objectType` inlined on a *property* rather than the CLT root) → `NESTED_TYPE: FAIL (<key>: <actual>)`. All match or no such properties exist → `NESTED_TYPE: ok`.
|
|
54
|
+
|
|
55
|
+
**Result:** all ok → `pass`. Otherwise `fail (<first failing check>)`.
|
|
56
|
+
|
|
57
|
+
**Failure → fix:** the renderer's `{!$attrs.outputValues.<field>}` paths cannot resolve unless `outputValues` is typed to the response CLT. Fix the envelope CLT's `outputValues.lightning:type` to `c__<responseCLT>`, ensure the response CLT exists, and remove any `$schema` / `items` keywords.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### 2. `renderer-wires-widget`
|
|
62
|
+
|
|
63
|
+
Confirms the envelope CLT's default renderer assigns the widget and binds every widget property through the nested `outputValues` path.
|
|
64
|
+
|
|
65
|
+
1. **File exists at the bundle root and parses** (NOT `lightningDesktopGenAi/`):
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
jq . <pkgDir>/lightningTypes/<toolCLT>/renderer.json > /dev/null && echo "PARSE: ok" || echo "PARSE: FAIL"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
2. **Definition points at this widget:**
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
jq -r '.renderer.componentOverrides["$"].definition' <pkgDir>/lightningTypes/<toolCLT>/renderer.json
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Expected: `@widget/c/<widgetName>`. Match → `DEFINITION: ok`; else `DEFINITION: FAIL (got <actual>)`.
|
|
78
|
+
|
|
79
|
+
3. **Attribute keys cover every widget schema property.** Print both lists; compare in reasoning:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
echo "SCHEMA_KEYS (expected):"
|
|
83
|
+
jq -r '.properties.attributes.properties | keys[]' <pkgDir>/uiWidgets/<widgetName>/schema.json | sort -u
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
echo "RENDERER_KEYS (actual):"
|
|
88
|
+
jq -r '.renderer.componentOverrides["$"].attributes | keys[]' <pkgDir>/lightningTypes/<toolCLT>/renderer.json | sort -u
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Same set → `ATTRIBUTES: ok`. Keys in SCHEMA not in RENDERER → `ATTRIBUTES: FAIL (missing: <list>)`. Keys in RENDERER not in SCHEMA → `ATTRIBUTES: FAIL (extra: <list>)`.
|
|
92
|
+
|
|
93
|
+
4. **Each binding uses the nested `outputValues` path.** Dump the map and inspect each entry:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
jq '.renderer.componentOverrides["$"].attributes' <pkgDir>/lightningTypes/<toolCLT>/renderer.json
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
For every key `K`, the value MUST equal `{!$attrs.outputValues.K}` exactly (nested path, matching key, no whitespace) — **unless** `K` is a leaf of a nested-object response field (per the response CLT's `@apexClassType` properties, see `clt-reference-integrity` check 4), in which case it MUST equal `{!$attrs.outputValues.<objectField>.K}` (three segments: `outputValues`, the object field, the leaf). All match their expected form → `BINDINGS: ok`. A flat `{!$attrs.K}` (missing `outputValues.`) or a one-level binding for a nested-object leaf (missing the `<objectField>.` segment) is a FAIL — these are the most common mistakes in this flow. Report `BINDINGS: FAIL (<key>: got <value>, expected <expected>)`.
|
|
100
|
+
|
|
101
|
+
**Result classification:**
|
|
102
|
+
- All checks pass → `pass`
|
|
103
|
+
- File missing / at wrong path / invalid JSON → `fail (renderer.json missing, mislocated, or invalid — must be at lightningTypes/<toolCLT>/renderer.json)`
|
|
104
|
+
- Definition mismatch → `fail (definition does not point at widget: got <actual>)`
|
|
105
|
+
- Coverage mismatch → `fail (missing bindings: <list>)` or `fail (extra bindings: <list>)`
|
|
106
|
+
- Flat or malformed binding → `fail (binding for <key> is not nested under outputValues: <actual>)`
|
|
107
|
+
|
|
108
|
+
**Failure → fix:** without correct nested wiring the widget either ships dead (no definition) or renders empty (flat bindings resolve against the envelope root, where the payload fields do not exist). Author the renderer per `references/two-clt-modeling.md`.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Warn — advisory
|
|
113
|
+
|
|
114
|
+
### `field-trace`
|
|
115
|
+
|
|
116
|
+
Enforces: no invented widget fields (subset rule) and no silent omission of response fields.
|
|
117
|
+
|
|
118
|
+
`INVOCABLE_FIELDS` and `WIDGET_PROPS` are labels in the printed output, NOT shell variables. Do NOT assign with `$(…)`.
|
|
119
|
+
|
|
120
|
+
1. **Extract the authoritative payload field names**, using the same source chosen in Phase 2:
|
|
121
|
+
|
|
122
|
+
**`action` source (preferred)** — read the Actions REST API `outputs` (already excludes inputs/helpers):
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
echo "INVOCABLE_FIELDS:"
|
|
126
|
+
sf api request rest '/services/data/v<APIVER>/actions/custom/apex/<ActionApiName>' -o <org> \
|
|
127
|
+
| jq -r '.outputs[].name' | sort -u
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**`apex` source** — grep the response class (scope to the response class block only; exclude the request class and private helpers):
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
echo "INVOCABLE_FIELDS:"
|
|
134
|
+
grep -A1 '@InvocableVariable' <pkgDir>/classes/<ClassName>.cls \
|
|
135
|
+
| grep -oE '(public|global)\s+[A-Za-z0-9_<>,\s]+\s+[a-zA-Z_][a-zA-Z0-9_]*\s*;' \
|
|
136
|
+
| sed -E 's/.*\s([a-zA-Z_][a-zA-Z0-9_]*)\s*;/\1/' \
|
|
137
|
+
| sort -u
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
If grep misses multi-line annotations, read the `.cls` with the Read tool and list fields manually. For the `sample` source, use the `outputValues` keys instead.
|
|
141
|
+
|
|
142
|
+
**Nested-object fields (per `references/mcp-tool-output-discovery.md` "Nested-object payload fields") expand before comparison.** A field resolved to `@apexClassType/<ns>__<OuterClass>$<InnerClass>` is not itself compared against `WIDGET_PROPS` — the widget flattens to that class's own leaf fields, never the object field. Replace that field name in `INVOCABLE_FIELDS` with its referenced class's leaf field names (its own `@InvocableVariable`/public members) before running the diff in step 3. Note the substitution in the printed output, e.g. `INVOCABLE_FIELDS (expanded): flightInfo → flightId, origin, destination, departureTime, arrivalTime, price`.
|
|
143
|
+
|
|
144
|
+
2. **Extract widget schema property keys:**
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
echo "WIDGET_PROPS:"
|
|
148
|
+
jq -r '.properties.attributes.properties | keys[]' <pkgDir>/uiWidgets/<widgetName>/schema.json | sort -u
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
3. **PRINT both lists** in the gate report (not just an assertion):
|
|
152
|
+
|
|
153
|
+
```text
|
|
154
|
+
INVOCABLE_FIELDS: accountName, accountIndustry, contactCount, status, ...
|
|
155
|
+
WIDGET_PROPS: accountName, accountIndustry, contactCount, ...
|
|
156
|
+
INVENTED (widget − invocable): <empty>
|
|
157
|
+
OMITTED (invocable − widget): status, ...
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
4. **Result classification:**
|
|
161
|
+
- `INVENTED` non-empty → **fail** (subset rule violated). `fail (invented: <list>)`.
|
|
162
|
+
- `OMITTED` non-empty AND every omitted field is in the Phase 3 `Properties omitted:` → **pass**.
|
|
163
|
+
- `OMITTED` non-empty AND any omitted field is NOT in `Properties omitted:` → **warn** (silent omission). `warn (silent omission: <list>)`, surface before the summary.
|
|
164
|
+
- Both empty → **pass**.
|
|
165
|
+
|
|
166
|
+
**Reporting `pass` without printing the two lists is a hard violation — report `not run` instead.**
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Direction of the subset rule
|
|
171
|
+
|
|
172
|
+
The widget `schema.json` and the response CLT `properties` are a **subset** of the response `@InvocableVariable` fields.
|
|
173
|
+
|
|
174
|
+
- **No invented fields (hard via `field-trace`).** The widget must not introduce properties the response class does not expose.
|
|
175
|
+
- **No silent omissions (warn).** The widget MAY omit response fields, but every omission must appear in the Phase 3 `Properties omitted:` section with a rationale.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Reporting
|
|
180
|
+
|
|
181
|
+
Phase 6 must list each gate's result by name: `pass`, `fail (<reason>)`, `warn (<reason>)`, or `not run`. Do not summarize as "all passed".
|
|
@@ -6,9 +6,13 @@ metadata:
|
|
|
6
6
|
minApiVersion: "67.0"
|
|
7
7
|
cliTools:
|
|
8
8
|
- tool: ["jq"]
|
|
9
|
-
semver: ">=1.6"
|
|
9
|
+
semver: ">=1.6.0"
|
|
10
|
+
- tool: ["node"]
|
|
11
|
+
semver: ">=18.0.0"
|
|
10
12
|
- tool: ["python3"]
|
|
11
|
-
semver: ">=3.
|
|
13
|
+
semver: ">=3.10.0"
|
|
14
|
+
- tool: ["sf"]
|
|
15
|
+
semver: ">=2.0.0"
|
|
12
16
|
---
|
|
13
17
|
|
|
14
18
|
# Salesforce Metadata API Skill
|
|
@@ -4,6 +4,11 @@ description: "ALWAYS USE THIS SKILL to retrieve metadata from an org to your loc
|
|
|
4
4
|
compatibility: Salesforce CLI (sf) v2+
|
|
5
5
|
metadata:
|
|
6
6
|
version: "1.0"
|
|
7
|
+
relatedSkills:
|
|
8
|
+
- "platform-metadata-deploy"
|
|
9
|
+
cliTools:
|
|
10
|
+
- tool: ["sf"]
|
|
11
|
+
semver: ">=2.0.0"
|
|
7
12
|
---
|
|
8
13
|
|
|
9
14
|
# platform-metadata-retrieve
|
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
name: platform-models-api-configure
|
|
3
3
|
description: "Configure (or troubleshoot) an AI coding agent or CLI to route through the Salesforce Models API using a signed OrgJWT. Use this skill when pointing an agent at the Salesforce model endpoint (api.salesforce.com/ai/gpt/v1), setting up OrgJWT / Bedrock-mode auth, wiring the agent's settings, API-key helper, and credentials file for the Salesforce endpoint, or fixing Models API 401 / 404 / \"model not available\" errors. DO NOT TRIGGER when the user needs to create or configure the Salesforce Connected App itself (use integration-connectivity-connected-app-configure) or set up Named Credentials / callout auth (use integration-connectivity-generate)."
|
|
4
4
|
metadata:
|
|
5
|
+
cliTools:
|
|
6
|
+
- tool: ["curl"]
|
|
7
|
+
semver: ">=7.29.0"
|
|
8
|
+
- tool: ["jq"]
|
|
9
|
+
semver: ">=1.6.0"
|
|
10
|
+
- tool: ["sf"]
|
|
11
|
+
semver: ">=2.0.0"
|
|
12
|
+
relatedSkills:
|
|
13
|
+
- "integration-connectivity-connected-app-configure"
|
|
14
|
+
- "integration-connectivity-generate"
|
|
5
15
|
version: "1.0"
|
|
6
16
|
---
|
|
7
17
|
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-permission-set-generate
|
|
3
3
|
description: "Generates correct, deployable Salesforce permission set metadata (PermissionSet XML) with object, field, user, and app permissions. Use this skill when creating or editing permission set metadata, object permissions, field-level security (FLS), tab visibility, or deploying permission sets."
|
|
4
|
-
compatibility: Salesforce Metadata API v60.0+
|
|
5
4
|
metadata:
|
|
6
|
-
author: sf-skills
|
|
7
5
|
version: "1.0"
|
|
6
|
+
minApiVersion: "60.0"
|
|
8
7
|
---
|
|
9
8
|
|
|
10
9
|
## When to Use This Skill
|
|
@@ -3,7 +3,7 @@ name: platform-report-generate
|
|
|
3
3
|
description: "Use this skill when users need to create, generate, or validate Salesforce Lightning Report metadata. Trigger when users mention reports, creating reports, report metadata, .report-meta.xml files, tabular reports, summary reports, matrix reports, joined reports, report columns, report groupings, report filters, report charts, cross-filters, bucket fields, report formulas, or report time frame filters. Also use when users say things like 'create a report', 'generate a report', 'build a report on Accounts', 'add a chart to my report', or when they encounter deployment errors for .report-meta.xml files. Do NOT trigger for: creating or modifying Custom Report Type metadata (.reportType-meta.xml — use platform-custom-report-type-generate), creating dashboards, creating list views, running or viewing existing reports in the UI, or SOQL queries."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.0"
|
|
6
|
-
minApiVersion: "
|
|
6
|
+
minApiVersion: "60.0"
|
|
7
7
|
relatedSkills:
|
|
8
8
|
- "platform-custom-report-type-generate"
|
|
9
9
|
mcpTools:
|
|
@@ -3,7 +3,7 @@ name: platform-sharing-rules-generate
|
|
|
3
3
|
description: "Use this skill when users need to create, edit, delete, or manage Salesforce Sharing Rules metadata. TRIGGER when: users mention sharing rules, record sharing, criteria-based sharing, role-based sharing, guest user sharing, sharingRules, sharingCriteriaRules, sharingGuestRules, sharingOwnerRules, .sharingRules-meta.xml files, or ask to share records with specific roles or groups. Also trigger when users want to modify or remove existing sharing rules, or update sharing rule criteria or access levels. DO NOT TRIGGER when user needs permission sets or profiles (use platform-permission-set-generate), or needs object-level security rather than record-level sharing (use platform-permission-set-generate)."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.2"
|
|
6
|
-
minApiVersion: "
|
|
6
|
+
minApiVersion: "60.0"
|
|
7
7
|
relatedSkills:
|
|
8
8
|
- "platform-custom-object-generate"
|
|
9
9
|
- "platform-permission-set-generate"
|
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
name: platform-soql-query
|
|
3
3
|
description: "SOQL query generation, optimization, and analysis with 100-point scoring. Use this skill when the user needs SOQL/SOSL authoring or optimization: natural-language-to-query generation, relationship queries, aggregates, query-plan analysis, and performance or safety improvements for Salesforce queries. TRIGGER when: user writes, optimizes, or debugs SOQL/SOSL queries, touches .soql files, or asks about relationship queries, aggregates, or query performance. DO NOT TRIGGER when: bulk data operations (use platform-data-manage), Apex DML logic (use platform-apex-generate), or report/dashboard queries."
|
|
4
4
|
metadata:
|
|
5
|
+
cliTools:
|
|
6
|
+
- tool: ["jq"]
|
|
7
|
+
semver: ">=1.6.0"
|
|
8
|
+
- tool: ["python3"]
|
|
9
|
+
semver: ">=3.10.0"
|
|
10
|
+
- tool: ["sf"]
|
|
11
|
+
semver: ">=2.0.0"
|
|
12
|
+
relatedSkills:
|
|
13
|
+
- "experience-lwc-generate"
|
|
14
|
+
- "platform-apex-generate"
|
|
15
|
+
- "platform-apex-logs-debug"
|
|
16
|
+
- "platform-apex-test-run"
|
|
17
|
+
- "platform-data-manage"
|
|
5
18
|
version: "1.1"
|
|
6
19
|
---
|
|
7
20
|
|
|
@@ -4,7 +4,11 @@ description: "Generate AgentforcePlatformTracingSettings metadata to enable or d
|
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.0"
|
|
6
6
|
minApiVersion: "68.0"
|
|
7
|
-
relatedSkills:
|
|
7
|
+
relatedSkills:
|
|
8
|
+
- "agentforce-observe"
|
|
9
|
+
- "integration-eventing-cdc-configure"
|
|
10
|
+
- "integration-eventing-subscription-configure"
|
|
11
|
+
- "platform-tracing-configure"
|
|
8
12
|
---
|
|
9
13
|
|
|
10
14
|
# Platform Tracing — Agentforce Configure
|
|
@@ -4,7 +4,10 @@ description: "Generate EventSettings metadata to enable or disable Platform Trac
|
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.0"
|
|
6
6
|
minApiVersion: "68.0"
|
|
7
|
-
relatedSkills:
|
|
7
|
+
relatedSkills:
|
|
8
|
+
- "integration-eventing-cdc-configure"
|
|
9
|
+
- "integration-eventing-subscription-configure"
|
|
10
|
+
- "platform-tracing-agentforce-configure"
|
|
8
11
|
---
|
|
9
12
|
|
|
10
13
|
# Platform Tracing — Configure
|