@salesforce/afv-skills 1.56.0 → 1.57.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/commerce-b2b-open-code-components-integrate/SKILL.md +1 -1
- package/skills/commerce-b2b-open-code-components-replace/SKILL.md +16 -16
- package/skills/dx-devops-project-manage/SKILL.md +1 -1
- package/skills/experience-cms-content-generate/SKILL.md +1 -1
- package/skills/experience-cms-content-render/SKILL.md +3 -3
- package/skills/experience-cms-content-render/assets/angular/MediaRenderer.component.ts +35 -7
- package/skills/experience-cms-content-render/assets/angular/cms-item.service.ts +13 -4
- package/skills/experience-cms-content-render/assets/react/MediaRenderer.tsx +30 -8
- package/skills/experience-cms-content-render/assets/react/useCmsItem.ts +14 -4
- package/skills/experience-cms-content-render/assets/shared/cmsCore.types.ts +11 -1
- package/skills/experience-cms-content-render/assets/shared/externalRefs.ts +1 -1
- package/skills/experience-cms-content-render/assets/shared/mediaLabels.ts +62 -0
- package/skills/experience-cms-content-render/references/init-scaffold.md +13 -6
- package/skills/experience-content-media-stock-image-search/SKILL.md +0 -1
- package/skills/experience-lwc-design-generate/SKILL.md +1 -1
- package/skills/experience-lwc-legacy-migrate/SKILL.md +212 -0
- package/skills/experience-lwc-legacy-migrate/assets/lo20-host-page-template.html +192 -0
- package/skills/experience-lwc-legacy-migrate/references/aura-to-lwc-completeness-checklist.md +188 -0
- package/skills/experience-lwc-legacy-migrate/references/lightning-out-2-system-reference.md +495 -0
- package/skills/experience-lwc-legacy-migrate/references/lightning-out-beta-to-2-migration.md +824 -0
- package/skills/experience-lwc-legacy-migrate/scripts/convert-lo-names.py +94 -0
- package/skills/experience-lwc-legacy-migrate/scripts/validate-lo20-page.py +133 -0
- package/skills/experience-ui-bundle-project-generate/SKILL.md +1 -1
- package/skills/integration-connectivity-connected-app-configure/SKILL.md +5 -5
- package/skills/integration-connectivity-generate/SKILL.md +10 -10
- package/skills/integration-connectivity-generate/scripts/configure-named-credential.sh +2 -2
- package/skills/platform-apex-test-generate/SKILL.md +1 -1
- package/skills/platform-apex-test-run/SKILL.md +1 -1
- package/skills/platform-custom-field-generate/SKILL.md +1 -1
- package/skills/platform-custom-lightning-type-generate/SKILL.md +1 -1
- package/skills/platform-custom-metadata-type-generate/SKILL.md +1 -1
- package/skills/platform-custom-object-generate/SKILL.md +1 -1
- package/skills/platform-custom-report-type-generate/SKILL.md +1 -1
- package/skills/platform-custom-setting-generate/SKILL.md +1 -1
- package/skills/platform-data-and-tooling-api-context-get/SKILL.md +1 -1
- package/skills/platform-data-manage/SKILL.md +10 -10
- package/skills/platform-flexipage-generate/SKILL.md +1 -1
- package/skills/platform-lightning-app-coordinate/SKILL.md +1 -1
- package/skills/platform-metadata-api-context-get/SKILL.md +1 -1
- package/skills/platform-metadata-retrieve/SKILL.md +1 -1
- package/skills/platform-permission-set-generate/SKILL.md +1 -1
- package/skills/platform-report-generate/SKILL.md +1 -1
- package/skills/platform-salesforce-connect-adapter-generate/SKILL.md +4 -4
- package/skills/platform-sharing-owd-configure/SKILL.md +1 -1
- package/skills/platform-sharing-rules-generate/SKILL.md +1 -1
- package/skills/platform-soql-query/SKILL.md +1 -1
- package/skills/platform-value-set-generate/SKILL.md +1 -1
- package/skills/service-agentforce-human-escalation-configure/SKILL.md +4 -0
- package/skills/service-agentforce-human-escalation-configure/scripts/tests/_bootstrap.py +26 -6
- package/skills/service-agentforce-human-escalation-configure/scripts/tests/test_escalation_contracts.py +5 -4
- package/skills/service-de-waba-integrate/SKILL.md +2 -1
- package/skills/service-digital-engagement-deployment-configure/SKILL.md +2 -0
- package/skills/service-digital-engagement-deployment-configure/scripts/check-api-version.sh +29 -0
- package/skills/service-email-to-case-configure/SKILL.md +1 -1
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Deterministic Lightning Out Beta -> LO 2.0 name/URL transforms.
|
|
3
|
+
|
|
4
|
+
The Beta -> LO 2.0 migration includes a few *purely mechanical* string
|
|
5
|
+
conversions that must be applied identically every time (Workflow B, Step B3):
|
|
6
|
+
|
|
7
|
+
* Aura component id ``c:myComponent`` -> LWC custom-element tag ``c-my-component``
|
|
8
|
+
* camelCase attribute names -> kebab-case HTML attribute names
|
|
9
|
+
* the org My Domain -> the versioned LO 2.0 library ``<script>`` URL
|
|
10
|
+
|
|
11
|
+
This script performs those conversions so the workflow never has to hand-derive
|
|
12
|
+
them. It does NOT make any judgement calls (target DOM location, whether an LO
|
|
13
|
+
2.0 App id is needed, placeholder values) -- those stay in the skill body.
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
python3 scripts/convert-lo-names.py \
|
|
17
|
+
--component c:myComponent \
|
|
18
|
+
--attributes recordId,ownerId,showRevenue \
|
|
19
|
+
--my-domain https://acme.my.salesforce.com
|
|
20
|
+
|
|
21
|
+
Any of the flags may be omitted; only the requested conversions are printed.
|
|
22
|
+
Exit code is 0 on success, 2 on a malformed argument.
|
|
23
|
+
"""
|
|
24
|
+
import argparse
|
|
25
|
+
import re
|
|
26
|
+
import sys
|
|
27
|
+
|
|
28
|
+
LO2_LIBRARY_PATH = "/lightning/lightning.out.latest/index.iife.prod.js"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def camel_to_kebab(name: str) -> str:
|
|
32
|
+
"""myComponent / MyComponent / my_component -> my-component."""
|
|
33
|
+
name = name.strip().replace("_", "-")
|
|
34
|
+
# split camelCase / PascalCase boundaries
|
|
35
|
+
name = re.sub(r"([a-z0-9])([A-Z])", r"\1-\2", name)
|
|
36
|
+
name = re.sub(r"([A-Z]+)([A-Z][a-z])", r"\1-\2", name)
|
|
37
|
+
return name.lower()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def component_tag(aura_id: str) -> str:
|
|
41
|
+
"""c:myComponent -> c-my-component (namespace preserved)."""
|
|
42
|
+
aura_id = aura_id.strip()
|
|
43
|
+
if ":" in aura_id:
|
|
44
|
+
ns, name = aura_id.split(":", 1)
|
|
45
|
+
else:
|
|
46
|
+
ns, name = "c", aura_id
|
|
47
|
+
return f"{ns.strip().lower()}-{camel_to_kebab(name)}"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def library_url(my_domain: str) -> str:
|
|
51
|
+
"""Normalize a My Domain to the versioned LO 2.0 library URL."""
|
|
52
|
+
d = my_domain.strip().rstrip("/")
|
|
53
|
+
if not d.startswith("http"):
|
|
54
|
+
d = "https://" + d
|
|
55
|
+
# Beta hosts on *.lightning.force.com; LO 2.0 must load from *.my.salesforce.com
|
|
56
|
+
d = d.replace(".lightning.force.com", ".my.salesforce.com")
|
|
57
|
+
# strip any path the caller pasted, keep scheme://host
|
|
58
|
+
m = re.match(r"(https?://[^/]+)", d)
|
|
59
|
+
host = m.group(1) if m else d
|
|
60
|
+
return f"{host}{LO2_LIBRARY_PATH}"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def main(argv=None) -> int:
|
|
64
|
+
p = argparse.ArgumentParser(description=__doc__,
|
|
65
|
+
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
66
|
+
p.add_argument("--component", help="Beta component id, e.g. c:myComponent")
|
|
67
|
+
p.add_argument("--attributes",
|
|
68
|
+
help="comma/space separated camelCase attribute names")
|
|
69
|
+
p.add_argument("--my-domain",
|
|
70
|
+
help="org My Domain or Beta host URL")
|
|
71
|
+
args = p.parse_args(argv)
|
|
72
|
+
|
|
73
|
+
if not (args.component or args.attributes or args.my_domain):
|
|
74
|
+
p.print_help()
|
|
75
|
+
return 2
|
|
76
|
+
|
|
77
|
+
if args.component:
|
|
78
|
+
print(f"component-tag: <{component_tag(args.component)}>")
|
|
79
|
+
|
|
80
|
+
if args.attributes:
|
|
81
|
+
raw = [a for a in re.split(r"[,\s]+", args.attributes) if a]
|
|
82
|
+
pairs = [(a, camel_to_kebab(a)) for a in raw]
|
|
83
|
+
print("attributes:")
|
|
84
|
+
for src, dst in pairs:
|
|
85
|
+
print(f" {src} -> {dst}")
|
|
86
|
+
|
|
87
|
+
if args.my_domain:
|
|
88
|
+
print(f"library-url: {library_url(args.my_domain)} (add the `async` attribute)")
|
|
89
|
+
|
|
90
|
+
return 0
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
if __name__ == "__main__":
|
|
94
|
+
sys.exit(main())
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Mechanically validate a migrated Lightning Out 2.0 host page.
|
|
3
|
+
|
|
4
|
+
The six non-negotiable LO 2.0 rules (Workflow B, Step B4) plus the core
|
|
5
|
+
library/component checklist items are all *deterministic code-structure*
|
|
6
|
+
checks. This script runs them against a migrated HTML host page so the
|
|
7
|
+
workflow gates on a repeatable pass/fail instead of prose interpretation.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
python3 scripts/validate-lo20-page.py <path-to-migrated.html>
|
|
11
|
+
|
|
12
|
+
Prints one PASS/FAIL line per rule. Exits 0 only when every rule passes;
|
|
13
|
+
exits 1 if any rule fails, 2 on a usage/IO error.
|
|
14
|
+
"""
|
|
15
|
+
import re
|
|
16
|
+
import sys
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def check(src: str):
|
|
20
|
+
"""Return a list of (ok: bool, label: str, detail: str)."""
|
|
21
|
+
results = []
|
|
22
|
+
|
|
23
|
+
def add(ok, label, detail=""):
|
|
24
|
+
results.append((ok, label, detail))
|
|
25
|
+
|
|
26
|
+
# --- Library / Beta removal -------------------------------------------
|
|
27
|
+
# Locate the versioned library path, then scan back to the opening
|
|
28
|
+
# <script to check for `async`. We do NOT isolate the tag with [^>]*
|
|
29
|
+
# because placeholder URLs like https://<DOMAIN>.my.salesforce.com
|
|
30
|
+
# legitimately contain a '>' inside the attribute value.
|
|
31
|
+
lib_path = "lightning.out.latest/index.iife.prod.js"
|
|
32
|
+
idx = src.find(lib_path)
|
|
33
|
+
has_lo2_lib = idx != -1
|
|
34
|
+
lib_async = False
|
|
35
|
+
if has_lo2_lib:
|
|
36
|
+
start = src.rfind("<script", 0, idx)
|
|
37
|
+
if start != -1:
|
|
38
|
+
lib_async = bool(re.search(r"\basync\b", src[start:idx]))
|
|
39
|
+
add(has_lo2_lib and lib_async, "LO 2.0 library script tag",
|
|
40
|
+
"must load .../lightning.out.latest/index.iife.prod.js with `async`")
|
|
41
|
+
|
|
42
|
+
beta_lib = bool(re.search(r"lightning\.force\.com/[^\"']*lightning\.out\.js", src))
|
|
43
|
+
beta_calls = bool(re.search(r"\$Lightning\.(use|createComponent)", src))
|
|
44
|
+
add(not beta_lib and not beta_calls, "No Lightning Out Beta remnants",
|
|
45
|
+
"no lightning.out.js / $Lightning.use / $Lightning.createComponent")
|
|
46
|
+
|
|
47
|
+
# --- Rule 1: customElements.whenDefined must use a literal string ------
|
|
48
|
+
wd = re.findall(r"customElements\.whenDefined\(\s*([^)]*?)\s*\)", src)
|
|
49
|
+
if not wd:
|
|
50
|
+
add(False, "Rule 1: whenDefined literal string",
|
|
51
|
+
"no customElements.whenDefined(...) call found")
|
|
52
|
+
else:
|
|
53
|
+
# Require the ENTIRE trimmed argument to be a single quoted string
|
|
54
|
+
# literal. A prefix-only check (starts with a quote) would let
|
|
55
|
+
# expressions like `'c-' + componentTag` slip through.
|
|
56
|
+
all_literal = all(
|
|
57
|
+
re.fullmatch(r"""(['"]).*?\1""", arg.strip()) for arg in wd)
|
|
58
|
+
add(all_literal, "Rule 1: whenDefined literal string",
|
|
59
|
+
"argument must be a quoted string, not the `components` variable")
|
|
60
|
+
|
|
61
|
+
# --- Rule 2: mountLo20 declared with two parameters -------------------
|
|
62
|
+
decl = re.search(r"function\s+mountLo20\s*\(([^)]*)\)", src)
|
|
63
|
+
if not decl:
|
|
64
|
+
add(False, "Rule 2: mountLo20(frontdoorUrl, orgUrl)",
|
|
65
|
+
"no `function mountLo20(...)` declaration found")
|
|
66
|
+
else:
|
|
67
|
+
params = [p for p in decl.group(1).split(",") if p.strip()]
|
|
68
|
+
add(len(params) == 2, "Rule 2: mountLo20(frontdoorUrl, orgUrl)",
|
|
69
|
+
f"declaration has {len(params)} parameter(s), expected 2")
|
|
70
|
+
|
|
71
|
+
# --- Rule 3: clearCachedResult present (called before mounting) -------
|
|
72
|
+
add(bool(re.search(r"clearCachedResult\s*\(", src)),
|
|
73
|
+
"Rule 3: clearCachedResult() before mount",
|
|
74
|
+
"clearCachedResult() must run before every mountLo20() call")
|
|
75
|
+
|
|
76
|
+
# --- Rule 4: every mountLo20 call passes two arguments ----------------
|
|
77
|
+
calls = re.findall(r"(?<!function\s)\bmountLo20\s*\(([^)]*)\)", src)
|
|
78
|
+
# Count args for EVERY call site (the declaration is excluded by the
|
|
79
|
+
# lookbehind). Do NOT skip empty argument lists: a zero-arg
|
|
80
|
+
# `mountLo20()` has an arg count of 0, which is != 2 and must fail.
|
|
81
|
+
bad_calls = [c for c in calls
|
|
82
|
+
if len([a for a in c.split(",") if a.strip()]) != 2]
|
|
83
|
+
add(len(bad_calls) == 0, "Rule 4: mountLo20 calls pass two args",
|
|
84
|
+
f"{len(bad_calls)} call(s) do not pass exactly two arguments")
|
|
85
|
+
|
|
86
|
+
# --- Rule 5: boot() wrapper defined and invoked -----------------------
|
|
87
|
+
boot_def = bool(re.search(r"function\s+boot\s*\(", src))
|
|
88
|
+
boot_call = bool(re.search(r"(?<!function\s)\bboot\s*\(\s*\)", src))
|
|
89
|
+
add(boot_def and boot_call, "Rule 5: boot() wrapper",
|
|
90
|
+
"define function boot() and call boot() once at the end")
|
|
91
|
+
|
|
92
|
+
# --- Rule 6: component tag has no inline display style ----------------
|
|
93
|
+
comp_tags = re.findall(r"<c-[a-z0-9-]+[^>]*>", src)
|
|
94
|
+
add(len(comp_tags) > 0, "Component tag present",
|
|
95
|
+
"expected a <c-...> custom element in the HTML")
|
|
96
|
+
inline_hidden = any(re.search(r"style\s*=\s*['\"][^'\"]*display\s*:\s*none",
|
|
97
|
+
t) for t in comp_tags)
|
|
98
|
+
add(not inline_hidden, "Rule 6: no inline display:none on component tag",
|
|
99
|
+
"control visibility via the loading indicator, not the component tag")
|
|
100
|
+
|
|
101
|
+
return results
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def main(argv=None) -> int:
|
|
105
|
+
argv = argv if argv is not None else sys.argv[1:]
|
|
106
|
+
if len(argv) != 1:
|
|
107
|
+
print("usage: validate-lo20-page.py <path-to-migrated.html>",
|
|
108
|
+
file=sys.stderr)
|
|
109
|
+
return 2
|
|
110
|
+
try:
|
|
111
|
+
with open(argv[0], "r", encoding="utf-8") as fh:
|
|
112
|
+
src = fh.read()
|
|
113
|
+
except OSError as e:
|
|
114
|
+
print(f"error: cannot read {argv[0]}: {e}", file=sys.stderr)
|
|
115
|
+
return 2
|
|
116
|
+
|
|
117
|
+
results = check(src)
|
|
118
|
+
failed = 0
|
|
119
|
+
for ok, label, detail in results:
|
|
120
|
+
mark = "PASS" if ok else "FAIL"
|
|
121
|
+
line = f"[{mark}] {label}"
|
|
122
|
+
if not ok and detail:
|
|
123
|
+
line += f" -- {detail}"
|
|
124
|
+
print(line)
|
|
125
|
+
if not ok:
|
|
126
|
+
failed += 1
|
|
127
|
+
|
|
128
|
+
print(f"\n{len(results) - failed}/{len(results)} checks passed")
|
|
129
|
+
return 0 if failed == 0 else 1
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
if __name__ == "__main__":
|
|
133
|
+
sys.exit(main())
|
|
@@ -113,4 +113,4 @@ From here, continue development with the other ui-bundle skills (`experience-ui-
|
|
|
113
113
|
|
|
114
114
|
- The starters are **minimal** — no seeded sample data or custom objects. Build the rest with the other ui-bundle skills.
|
|
115
115
|
- These templates use the `uiBundles` metadata convention. The UI bundle directory and meta XML are named after the project name you pass to `--name`.
|
|
116
|
-
- `sf template generate project --help` lists all available templates if the flag names ever change.
|
|
116
|
+
- `sf template generate project --help` lists all available templates if the flag names ever change.
|
|
@@ -38,8 +38,8 @@ Use this skill when the user needs **OAuth app configuration** in Salesforce: Co
|
|
|
38
38
|
|
|
39
39
|
**Out of scope — delegate elsewhere:**
|
|
40
40
|
- Configuring Named Credentials or runtime callouts → [integration-connectivity-generate](../integration-connectivity-generate/SKILL.md)
|
|
41
|
-
- Deploying metadata to orgs →
|
|
42
|
-
- Writing Apex token-handling code →
|
|
41
|
+
- Deploying metadata to orgs → the `platform-metadata-deploy` skill
|
|
42
|
+
- Writing Apex token-handling code → the `platform-apex-generate` skill
|
|
43
43
|
|
|
44
44
|
---
|
|
45
45
|
|
|
@@ -206,8 +206,8 @@ Score: <x>/120
|
|
|
206
206
|
| Need | Delegate to | Reason |
|
|
207
207
|
|---|---|---|
|
|
208
208
|
| Named Credential / callout runtime config | [integration-connectivity-generate](../integration-connectivity-generate/SKILL.md) | runtime integration setup |
|
|
209
|
-
| Deploy app metadata |
|
|
210
|
-
| Apex token or refresh handling |
|
|
209
|
+
| Deploy app metadata | `platform-metadata-deploy` skill | org validation and deployment |
|
|
210
|
+
| Apex token or refresh handling | `platform-apex-generate` skill | implementation logic |
|
|
211
211
|
|
|
212
212
|
---
|
|
213
213
|
|
|
@@ -237,4 +237,4 @@ Score: <x>/120
|
|
|
237
237
|
| `references/security-checklist.md` | Step 4 — full 120-point security scoring checklist |
|
|
238
238
|
| `references/testing-validation-guide.md` | Step 5 — pre-deployment validation and testing guide |
|
|
239
239
|
| `references/migration-guide.md` | When migrating from Connected App to ECA patterns |
|
|
240
|
-
| `references/example-usage.md` | Full end-to-end examples for common OAuth scenarios |
|
|
240
|
+
| `references/example-usage.md` | Full end-to-end examples for common OAuth scenarios |
|
|
@@ -39,9 +39,9 @@ Use `integration-connectivity-generate` when the work involves:
|
|
|
39
39
|
|
|
40
40
|
Delegate elsewhere when the user is:
|
|
41
41
|
- configuring the OAuth app itself → [integration-connectivity-connected-app-configure](../integration-connectivity-connected-app-configure/SKILL.md)
|
|
42
|
-
- writing Apex-only business logic →
|
|
43
|
-
- deploying metadata →
|
|
44
|
-
- importing/exporting data →
|
|
42
|
+
- writing Apex-only business logic → the `platform-apex-generate` skill
|
|
43
|
+
- deploying metadata → the `platform-metadata-deploy` skill
|
|
44
|
+
- importing/exporting data → the `platform-data-manage` skill
|
|
45
45
|
|
|
46
46
|
---
|
|
47
47
|
|
|
@@ -93,9 +93,9 @@ Check:
|
|
|
93
93
|
|
|
94
94
|
### 5. Hand off deployment or implementation details
|
|
95
95
|
Use:
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
-
-
|
|
96
|
+
- the `platform-metadata-deploy` skill for deployment
|
|
97
|
+
- the `platform-apex-generate` skill for deeper service / retry code
|
|
98
|
+
- the `automation-flow-generate` skill for declarative HTTP callout orchestration
|
|
99
99
|
|
|
100
100
|
---
|
|
101
101
|
|
|
@@ -142,10 +142,10 @@ Next step: <deploy, register, test, or implement>
|
|
|
142
142
|
| Need | Delegate to | Reason |
|
|
143
143
|
|---|---|---|
|
|
144
144
|
| OAuth app setup | [integration-connectivity-connected-app-configure](../integration-connectivity-connected-app-configure/SKILL.md) | consumer key / cert / app config |
|
|
145
|
-
| advanced callout service code |
|
|
146
|
-
| declarative HTTP callout / Flow wrapper |
|
|
147
|
-
| deploy integration metadata |
|
|
148
|
-
| use integration from Agentforce |
|
|
145
|
+
| advanced callout service code | `platform-apex-generate` skill | Apex implementation |
|
|
146
|
+
| declarative HTTP callout / Flow wrapper | `automation-flow-generate` skill | Flow orchestration |
|
|
147
|
+
| deploy integration metadata | `platform-metadata-deploy` skill | validation and rollout |
|
|
148
|
+
| use integration from Agentforce | `agentforce-generate` skill | agent action composition |
|
|
149
149
|
|
|
150
150
|
---
|
|
151
151
|
|
|
@@ -190,14 +190,14 @@ try {
|
|
|
190
190
|
// Create the credential (first-time setup)
|
|
191
191
|
ConnectApi.NamedCredentials.createCredential(newCredentials);
|
|
192
192
|
System.debug('✓ External Credential configured successfully!');
|
|
193
|
-
System.debug('Principal: $
|
|
193
|
+
System.debug('Principal: $PRINCIPAL_NAME_ESCAPED');
|
|
194
194
|
} catch (Exception e) {
|
|
195
195
|
// If already exists, try patching instead
|
|
196
196
|
if (e.getMessage().contains('already exists')) {
|
|
197
197
|
try {
|
|
198
198
|
ConnectApi.NamedCredentials.patchCredential(newCredentials);
|
|
199
199
|
System.debug('✓ External Credential updated successfully!');
|
|
200
|
-
System.debug('Principal: $
|
|
200
|
+
System.debug('Principal: $PRINCIPAL_NAME_ESCAPED');
|
|
201
201
|
} catch (Exception e2) {
|
|
202
202
|
System.debug('✗ Error updating credential: ' + e2.getMessage());
|
|
203
203
|
throw e2;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-apex-test-generate
|
|
3
|
-
description: "
|
|
3
|
+
description: "Use to generate and validate Apex test classes with TestDataFactory patterns, bulk testing (251+ records), mocking, assertions, and disciplined test-fix loops. Use when creating Apex test classes (for triggers, services, controllers, batch jobs, queueables, and callouts), improving coverage, debugging or fixing failing Apex tests, or running test/coverage analysis. Triggers on *Test.cls files, sf apex run test, coverage reports. Do NOT trigger for production Apex (use platform-apex-generate) or Jest/LWC tests."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.1"
|
|
6
6
|
domains: ["Platform"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-apex-test-run
|
|
3
|
-
description: "Apex test execution, coverage analysis, and test-fix loops with 120-point scoring. Use when the user
|
|
3
|
+
description: "Apex test execution, coverage analysis, and test-fix loops with 120-point scoring. Use when the user runs Apex tests, checks code coverage, fixes failing tests, or touches *Test.cls / *_Test.cls files. DO NOT TRIGGER when writing Apex production code (use platform-apex-generate), Agentforce agent testing (use agentforce-test), or Jest/LWC tests (use experience-lwc-generate)."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.2"
|
|
6
6
|
domains: ["Platform"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-custom-field-generate
|
|
3
|
-
description: "Use
|
|
3
|
+
description: "Use when users create, generate, or validate Salesforce Custom Field metadata. Trigger on custom fields, field types, Roll-Up Summary, Master-Detail/Lookup relationships, formula fields, picklists, dependent (controlling) picklists, referencing a value set from a field, or scoping picklist values per record type; also field deployment errors, including a record type that won't deploy without a business process. DO NOT TRIGGER for creating/customizing the value set itself — a new GlobalValueSet or a StandardValueSet catalog like Industry — use platform-value-set-generate; this skill covers the field that references a value set, not the value set definition."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.0"
|
|
6
6
|
domains: ["Platform"]
|
|
@@ -178,4 +178,4 @@ When you need the full list of supported primitive `lightning:type` identifiers,
|
|
|
178
178
|
- [ ] Layout configurations use `lightning/propertyLayout` with ONLY the `property` attribute (no `label`, `title`, or other attributes)
|
|
179
179
|
- [ ] All attribute mappings (`{!$attrs.propertyName}`) reference properties that exist in the type schema
|
|
180
180
|
- [ ] Custom LWC components have correct targets in `-meta.xml`: `lightning__AgentforceInput` for editors, `lightning__AgentforceOutput` for renderers
|
|
181
|
-
- [ ] Root schema does NOT include `"$schema"` field
|
|
181
|
+
- [ ] Root schema does NOT include `"$schema"` field
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-custom-metadata-type-generate
|
|
3
|
-
description: "Use
|
|
3
|
+
description: "Use to create, generate, or validate Salesforce Custom Metadata Type metadata — the __mdt object, fields, and deployable records. Trigger on custom metadata types, CMDT, __mdt objects, .md-meta.xml files, or cross-org reference/config data; also admin-maintained mapping/lookup/crosswalk tables (config that changes without a deploy belongs in a CMDT, never hardcoded in Apex/Flow), and CMDT deploy errors. DO NOT TRIGGER for Custom Settings (use platform-custom-setting-generate), business-record objects (use platform-custom-object-generate), or secrets/API keys (use a Named Credential)."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.0"
|
|
6
6
|
minApiVersion: "60.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-custom-object-generate
|
|
3
|
-
description: "Use
|
|
3
|
+
description: "Use when users create, generate, or validate Salesforce Custom Object metadata. Trigger on custom objects, .object files, sharing models, name fields, or validation rules — e.g. \"create a custom object\" — and deployment errors around sharing models and Master-Detail relationships. Also keep the object's <description> current when its fields or validation rules change. Do NOT use for non-Custom-Object metadata (Apex, Flows, LWC, Permission Sets, Custom Metadata Types) or standard objects."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.1"
|
|
6
6
|
domains: ["Platform"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-custom-report-type-generate
|
|
3
|
-
description: "Use
|
|
3
|
+
description: "Use to create, generate, or validate Salesforce Custom Report Type metadata. Trigger on custom report types, CRTs, cross-object reports, report builder data sources, exposing fields for reporting across related objects, inner vs outer joins in reports, report type categories, or deployment errors for .reportType-meta.xml files. Do NOT trigger for running, editing, or filtering existing reports; creating report folders, dashboards, or list views; or non-authoring reporting questions."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.0"
|
|
6
6
|
domains: ["Platform"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-custom-setting-generate
|
|
3
|
-
description: "Use
|
|
3
|
+
description: "Use to create, generate, or validate Salesforce Custom Setting metadata. Trigger on custom settings (hierarchy/list), customSettingsType, SetupOwnerId, per-profile/per-user config overrides, feature flags/toggles, kill switches, or admin on/off switches (e.g. bypass triggers during a data load); also \"create a custom setting\" or a setting that silently deployed as a regular object. A kill switch is just a checkbox on a hierarchy setting — generate ONLY the setting, never an Apex trigger/handler. DO NOT TRIGGER for Custom Metadata Types (use platform-custom-metadata-type-generate), business-record objects (use platform-custom-object-generate), or secrets/tokens (use a Named Credential)."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.0"
|
|
6
6
|
minApiVersion: "60.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-data-and-tooling-api-context-get
|
|
3
|
-
description: "Authoritative field/schema reference for 2130 STANDARD Salesforce objects —
|
|
3
|
+
description: "Authoritative field/schema reference for 2130 STANDARD Salesforce objects — sObject and Tooling field API names, types, properties (filterable/sortable/groupable/updateable), and relationships for Account, Contact, Opportunity, Lead, Case, ApexClass, and more. Load alongside a SOQL/Apex skill when fields/types/capabilities are unverified — not for query syntax or optimization alone. TRIGGER when verifying/debugging fields in a SOQL/SOSL query or DML against a standard object. Custom __c objects/fields are NOT covered — describe the live org (sf sobject describe). DO NOT TRIGGER for authoring/deploying *-meta.xml or sfdx source (use the Metadata API skill)."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.0"
|
|
6
6
|
domains: ["Platform"]
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-data-manage
|
|
3
|
-
description: "Salesforce data operations with 130-point scoring. Use
|
|
3
|
+
description: "Salesforce data operations with 130-point scoring. Use to create, update, delete, bulk import/export, generate test data, and clean up org records via sf CLI and anonymous Apex. TRIGGER on creating test data, bulk import/export, sf data CLI commands, data-factory patterns for Apex tests, or seeding/cleaning org records. DO NOT TRIGGER for SOQL query writing only (use platform-soql-query), Apex test execution (use platform-apex-test-run), or metadata deployment (use platform-metadata-deploy)."
|
|
4
4
|
metadata:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
semver: ">=1.6.0"
|
|
8
|
-
- tool: ["python3"]
|
|
9
|
-
semver: ">=3.8.0"
|
|
10
|
-
- tool: ["sf"]
|
|
11
|
-
semver: ">=2.0.0"
|
|
5
|
+
version: "1.1"
|
|
6
|
+
domains: ["Platform"]
|
|
12
7
|
relatedSkills:
|
|
13
8
|
- "automation-flow-generate"
|
|
14
9
|
- "platform-apex-generate"
|
|
@@ -17,8 +12,13 @@ metadata:
|
|
|
17
12
|
- "platform-custom-object-generate"
|
|
18
13
|
- "platform-metadata-deploy"
|
|
19
14
|
- "platform-soql-query"
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
cliTools:
|
|
16
|
+
- tool: ["sf"]
|
|
17
|
+
semver: ">=2.0.0"
|
|
18
|
+
- tool: ["jq"]
|
|
19
|
+
semver: ">=1.6.0"
|
|
20
|
+
- tool: ["python3"]
|
|
21
|
+
semver: ">=3.8.0"
|
|
22
22
|
---
|
|
23
23
|
|
|
24
24
|
# Salesforce Data Operations Expert (platform-data-manage)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-flexipage-generate
|
|
3
|
-
description: "Use
|
|
3
|
+
description: "Use when users create, generate, modify, or validate Salesforce Lightning pages (FlexiPages). Trigger on RecordPage, AppPage, HomePage, Lightning pages, adding components to a page, page customization (e.g. 'customize the record page'), or .flexipage-meta.xml files (regions, components, deployment errors). DO NOT TRIGGER for Visualforce pages, page layout assignments in the UI, UI Bundle/Experience Cloud site pages, or Aura/Lightning Web Component development without FlexiPage context."
|
|
4
4
|
allowed-tools: Bash Read Write
|
|
5
5
|
metadata:
|
|
6
6
|
version: "1.1"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-metadata-api-context-get
|
|
3
|
-
description: "REQUIRED companion for Salesforce metadata generation — load this schema/API-context skill in the SAME turn as ANY metadata
|
|
3
|
+
description: "REQUIRED companion for Salesforce metadata generation — load this schema/API-context skill in the SAME turn as ANY metadata generator (if you load a generator, you ALSO load this). Use whenever you create, generate, edit, or author metadata or a *-meta.xml file (custom object, field, flow, and 604 Metadata API types): it gives authoritative schema, required flags, and XML structure so files deploy cleanly. Trigger on *-meta.xml, metadata schema, api context. DO NOT use for SOQL, DML, runtime sObject access, or Tooling API records."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.0"
|
|
6
6
|
domains: ["Platform"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-metadata-retrieve
|
|
3
|
-
description: "ALWAYS USE THIS SKILL to retrieve metadata from an org to your local project
|
|
3
|
+
description: "ALWAYS USE THIS SKILL to retrieve metadata from an org to your local project with sf project retrieve start. Supports retrieval by all changes, source directory, metadata type (wildcards), manifest (package.xml), or package name, in source or metadata (ZIP) format. Use when the user asks to retrieve, pull, sync, or download metadata, Apex classes, or custom objects. DO NOT TRIGGER for deploying metadata (use platform-metadata-deploy), listing metadata, or generating a package.xml (use platform-manifest-generate). NEVER use MCP tools."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.0"
|
|
6
6
|
domains: ["Platform", "Developer Experience"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-report-generate
|
|
3
|
-
description: "Use
|
|
3
|
+
description: "Use when users create, generate, or validate Salesforce Lightning Report metadata (.report-meta.xml) — tabular, summary, matrix, or joined reports with columns, groupings, filters, charts, cross-filters, buckets, formulas, or time-frame filters. Triggers on \"create a report\", \"build a report\", \"add a chart\", or .report-meta.xml deploy errors. Do NOT trigger for Custom Report Type metadata (use platform-custom-report-type-generate), dashboards, list views, running reports in the UI, or SOQL."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.0"
|
|
6
6
|
domains: ["Platform"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-salesforce-connect-adapter-generate
|
|
3
|
-
description: "Custom Apex adapter generation for Salesforce Connect — connects any external REST API to Salesforce as live, queryable External Objects without ETL or
|
|
3
|
+
description: "Custom Apex adapter generation for Salesforce Connect — connects any external REST API to Salesforce as live, queryable External Objects without ETL or copying. TRIGGER when: connecting a non-standard external API, writing a DataSource.Provider/Connection or a `.cls`/`.cls-meta.xml` custom adapter class, adding a `.namedCredential-meta.xml` for the adapter's callout, surfacing external data as records, \"custom adapter\", \"ExternalId field\", \"DataSource namespace\", or whether custom Apex fits. DO NOT TRIGGER when: a standard adapter is already configured (OData, Snowflake), for copy/bulk-sync (use platform-data-manage), or for Apex callouts outside Connect (use platform-apex-generate or integration-connectivity-generate)."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.0"
|
|
6
6
|
minApiVersion: "66.0"
|
|
@@ -26,7 +26,7 @@ Route the user through building a complete custom Salesforce Connect Apex adapte
|
|
|
26
26
|
|
|
27
27
|
**In scope:** Generating `DataSource.Connection` and `DataSource.Provider` Apex classes, Named Credential metadata, deployment via sf CLI, and step-by-step Setup registration guidance for any REST API.
|
|
28
28
|
|
|
29
|
-
**Out of scope:** Configuring standard adapters (OData, Snowflake, GraphQL — those have their own flows). Generating the External Data Source metadata file (not deployable via sf CLI — must be registered manually in Setup). Writing Apex that calls external APIs outside the Salesforce Connect framework (use
|
|
29
|
+
**Out of scope:** Configuring standard adapters (OData, Snowflake, GraphQL — those have their own flows). Generating the External Data Source metadata file (not deployable via sf CLI — must be registered manually in Setup). Writing Apex that calls external APIs outside the Salesforce Connect framework (use the platform-apex-generate or integration-connectivity-generate skills).
|
|
30
30
|
|
|
31
31
|
## Before starting
|
|
32
32
|
|
|
@@ -37,11 +37,11 @@ Confirm two things. If either is missing, ask before proceeding.
|
|
|
37
37
|
| The user wants to… | Right tool |
|
|
38
38
|
|---|---|
|
|
39
39
|
| Query external data live without copying it — read-only or read-write, appears as Salesforce records | **This skill** |
|
|
40
|
-
| Copy or sync data into Salesforce on a schedule |
|
|
40
|
+
| Copy or sync data into Salesforce on a schedule | the platform-data-manage skill |
|
|
41
41
|
| Connect to OData, GraphQL, DynamoDB, Athena, or Cross-Org | Standard adapter setup — no Apex needed, different flow |
|
|
42
42
|
| Connect to Snowflake via Salesforce's native Snowflake adapter (direct Snowflake protocol) | Built-in Snowflake adapter — no Apex needed |
|
|
43
43
|
| Access Snowflake (or any database) data via a REST or HTTP API | **This skill** — Snowflake REST endpoint → custom Apex adapter |
|
|
44
|
-
| Call an external API from Apex or Flow logic |
|
|
44
|
+
| Call an external API from Apex or Flow logic | the platform-apex-generate skill or [integration-connectivity-generate](../integration-connectivity-generate/SKILL.md) |
|
|
45
45
|
| Expose Salesforce data to an external system | [integration-connectivity-generate](../integration-connectivity-generate/SKILL.md) |
|
|
46
46
|
| Receive real-time pushed data or subscribe to external events | Not Salesforce Connect — Connect is pull-only. Use Platform Events or Change Data Capture instead |
|
|
47
47
|
| Sync or copy data for analytics or bulk processing | Data Cloud or ETL — Connect is zero-copy virtualization only |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-sharing-owd-configure
|
|
3
|
-
description: "Use when the user wants to retrieve or update Organization-Wide Default (OWD) sharing settings for Salesforce objects. TRIGGER
|
|
3
|
+
description: "Use when the user wants to retrieve or update Organization-Wide Default (OWD) sharing settings for Salesforce objects. TRIGGER on org-wide defaults, checking/viewing sharing defaults, changing default access levels (Private, Public Read Only, Public Read/Write, Controlled by Parent), internal/external access for standard or custom objects, making records private, or sharingModel in .object-meta.xml files. DO NOT TRIGGER for sharing rules, criteria-based sharing, role hierarchy, or manual sharing — delegate to platform-sharing-rules-generate."
|
|
4
4
|
metadata:
|
|
5
5
|
relatedSkills:
|
|
6
6
|
- "platform-metadata-deploy"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-sharing-rules-generate
|
|
3
|
-
description: "Use
|
|
3
|
+
description: "Use when users get, create, edit, delete, or retrieve Salesforce Sharing Rules metadata for record-level access. TRIGGER on sharing rules, record/criteria-based/role-based/guest-user sharing, sharingCriteriaRules/sharingOwnerRules/sharingGuestRules, .sharingRules-meta.xml files, or sharing records with roles or groups, including viewing or modifying existing rules. DO NOT TRIGGER for permission sets/profiles or object-level (not record-level) security (use platform-permission-set-generate)."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.3"
|
|
6
6
|
domains: ["Platform"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-soql-query
|
|
3
|
-
description: "
|
|
3
|
+
description: "Use when the user needs SOQL/SOSL authoring or optimization: natural-language-to-query generation, relationship queries, aggregates, query-plan/selectivity analysis, and performance or safety improvements. TRIGGER when the user writes, optimizes, or debugs SOQL/SOSL, touches .soql files, or asks about relationship queries, aggregates, or query performance. DO NOT TRIGGER for bulk data operations (use platform-data-manage), Apex DML logic (use platform-apex-generate), or report/dashboard queries."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.1"
|
|
6
6
|
domains: ["Platform"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-value-set-generate
|
|
3
|
-
description: "Use
|
|
3
|
+
description: "Use to create, generate, or validate a Salesforce GlobalValueSet (reusable picklist shared across fields) or customize a StandardValueSet (built-in picklists like Industry, Lead Source, Opportunity Stage). Trigger on global/standard value set, reusable picklist, .globalValueSet-meta.xml or .standardValueSet-meta.xml, or deploy errors adding values to a standard picklist. DO NOT TRIGGER for a one-off inline picklist on a single field with no reuse — use platform-custom-field-generate."
|
|
4
4
|
metadata:
|
|
5
5
|
version: "1.0"
|
|
6
6
|
domains: ["Platform"]
|
|
@@ -196,6 +196,10 @@ A single JSON object to stdout:
|
|
|
196
196
|
|
|
197
197
|
Existing queue, `QueueSobject`, `QueueRoutingConfig`, queue members, and an already-active outbound flow are reused, not recreated (members are only added when the queue has zero active members and `QUEUE_MEMBER_USERNAMES` is supplied; already-present members are left untouched). The doc-driven edits (`canEscalate`, `outboundRouteConfigs`) are set-if-absent. A second run against a fully configured org performs no writes and returns `CONFIGURED`.
|
|
198
198
|
|
|
199
|
+
## Classifier contracts
|
|
200
|
+
|
|
201
|
+
Before investigating or changing any of the deterministic Node classifiers referenced above (`scripts/classify-agent-active.mjs`, `scripts/verify-escalation-config.mjs`, `scripts/extract-outbound-route.mjs`, `scripts/classify-nga-escalation.mjs`), read [references/classifier-contracts.md](references/classifier-contracts.md) for each one's exact input/output contract.
|
|
202
|
+
|
|
199
203
|
## Verification
|
|
200
204
|
|
|
201
205
|
Run the bundled escalation contract tests after changing this skill or its scripts:
|