Compare commits

...

6 Commits

Author SHA1 Message Date
dependabot[bot]
e92cb3a67a
chore(deps): bump esbuild and tsx
Bumps [esbuild](https://github.com/evanw/esbuild) to 0.28.1 and updates ancestor dependency [tsx](https://github.com/privatenumber/tsx). These dependencies need to be updated together.


Updates `esbuild` from 0.27.3 to 0.28.1
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.27.3...v0.28.1)

Updates `tsx` from 4.21.0 to 4.22.4
- [Release notes](https://github.com/privatenumber/tsx/releases)
- [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs)
- [Commits](https://github.com/privatenumber/tsx/compare/v4.21.0...v4.22.4)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.28.1
  dependency-type: indirect
- dependency-name: tsx
  dependency-version: 4.22.4
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-29 10:10:46 +00:00
svc-idee-bot
e89d8d17a8 chore(release): 1.27.0 [skip ci] 2026-06-29 10:08:25 +00:00
GitHub Action
fae028fd99 feat: Update stale cross-references to renamed skills @W-23223262@ 2026-06-29 10:08:01 +00:00
Hemant Singh Bisht
48ef93f39d
fix: @W-22259678@ update stale skill name references (#301)
fix: update stale skill name references to match new naming convention

- README.md: update folder structure examples from old names
  (generating-apex, generating-custom-object, generating-flow) to new
  names (platform-apex-generate, platform-custom-object-generate,
  automation-flow-generate)
- samples/AGENT.md (b2e + b2x): update using-ui-bundle-salesforce-data
  to experience-ui-bundle-salesforce-data-access
2026-06-29 12:32:07 +05:30
svc-idee-bot
7f223b0d41 chore(release): 1.26.0 [skip ci] 2026-06-26 17:15:52 +00:00
GitHub Action
77e5e1476c feat: release 4 new dx-devops skills @W-23195013@ 2026-06-26 17:15:29 +00:00
36 changed files with 1622 additions and 1095 deletions

View File

@ -1,3 +1,26 @@
# [1.27.0](https://github.com/forcedotcom/sf-skills/compare/1.26.0...1.27.0) (2026-06-29)
### Bug Fixes
* @W-22259678@ update stale skill name references ([#301](https://github.com/forcedotcom/sf-skills/issues/301)) ([48ef93f](https://github.com/forcedotcom/sf-skills/commit/48ef93f39d25792029ea3a4287c845d842706f6f))
### Features
* Update stale cross-references to renamed skills @W-23223262@ ([fae028f](https://github.com/forcedotcom/sf-skills/commit/fae028fd99a366de12a41d5e256020aee82ffe29))
# [1.26.0](https://github.com/forcedotcom/sf-skills/compare/1.25.0...1.26.0) (2026-06-26)
### Features
* release 4 new dx-devops skills @W-23195013@ ([77e5e14](https://github.com/forcedotcom/sf-skills/commit/77e5e1476c696c8c33910f21d43d3c555f755c9e))
# [1.25.0](https://github.com/forcedotcom/sf-skills/compare/1.24.0...1.25.0) (2026-06-26)

View File

@ -9,9 +9,9 @@ The skills are contributed by Salesforce and the broader community. Its optim
```
sf-skills/
├── skills/ # Directory-based executable workflows
│ ├── generating-apex/
│ ├── generating-custom-object/
│ ├── generating-flow/
│ ├── platform-apex-generate/
│ ├── platform-custom-object-generate/
│ ├── automation-flow-generate/
│ └── ...
├── samples/ # Synced sample apps (e.g. from npm)
│ └── ui-bundle-template-app-react-sample-b2e/

250
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "@salesforce/afv-skills",
"version": "1.13.0",
"version": "1.27.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@salesforce/afv-skills",
"version": "1.13.0",
"version": "1.27.0",
"license": "CC-BY-NC-4.0",
"devDependencies": {
"@salesforce/ui-bundle-template-app-react-sample-b2e": "^10.2.2",
@ -405,9 +405,9 @@
"license": "SEE LICENSE IN LICENSE.txt"
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz",
"integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz",
"integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==",
"cpu": [
"ppc64"
],
@ -422,9 +422,9 @@
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz",
"integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz",
"integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==",
"cpu": [
"arm"
],
@ -439,9 +439,9 @@
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz",
"integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz",
"integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==",
"cpu": [
"arm64"
],
@ -456,9 +456,9 @@
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz",
"integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz",
"integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==",
"cpu": [
"x64"
],
@ -473,9 +473,9 @@
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz",
"integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz",
"integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==",
"cpu": [
"arm64"
],
@ -490,9 +490,9 @@
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz",
"integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz",
"integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==",
"cpu": [
"x64"
],
@ -507,9 +507,9 @@
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz",
"integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz",
"integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==",
"cpu": [
"arm64"
],
@ -524,9 +524,9 @@
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz",
"integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz",
"integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==",
"cpu": [
"x64"
],
@ -541,9 +541,9 @@
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz",
"integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz",
"integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==",
"cpu": [
"arm"
],
@ -558,9 +558,9 @@
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz",
"integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz",
"integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==",
"cpu": [
"arm64"
],
@ -575,9 +575,9 @@
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz",
"integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz",
"integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==",
"cpu": [
"ia32"
],
@ -592,9 +592,9 @@
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz",
"integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz",
"integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==",
"cpu": [
"loong64"
],
@ -609,9 +609,9 @@
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz",
"integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz",
"integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==",
"cpu": [
"mips64el"
],
@ -626,9 +626,9 @@
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz",
"integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz",
"integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==",
"cpu": [
"ppc64"
],
@ -643,9 +643,9 @@
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz",
"integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz",
"integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==",
"cpu": [
"riscv64"
],
@ -660,9 +660,9 @@
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz",
"integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz",
"integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==",
"cpu": [
"s390x"
],
@ -677,9 +677,9 @@
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz",
"integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz",
"integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==",
"cpu": [
"x64"
],
@ -694,9 +694,9 @@
}
},
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz",
"integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz",
"integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==",
"cpu": [
"arm64"
],
@ -711,9 +711,9 @@
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz",
"integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz",
"integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==",
"cpu": [
"x64"
],
@ -728,9 +728,9 @@
}
},
"node_modules/@esbuild/openbsd-arm64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz",
"integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz",
"integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==",
"cpu": [
"arm64"
],
@ -745,9 +745,9 @@
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz",
"integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz",
"integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==",
"cpu": [
"x64"
],
@ -762,9 +762,9 @@
}
},
"node_modules/@esbuild/openharmony-arm64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz",
"integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz",
"integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==",
"cpu": [
"arm64"
],
@ -779,9 +779,9 @@
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz",
"integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz",
"integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==",
"cpu": [
"x64"
],
@ -796,9 +796,9 @@
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz",
"integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz",
"integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==",
"cpu": [
"arm64"
],
@ -813,9 +813,9 @@
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz",
"integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz",
"integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==",
"cpu": [
"ia32"
],
@ -830,9 +830,9 @@
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz",
"integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz",
"integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==",
"cpu": [
"x64"
],
@ -1736,9 +1736,9 @@
}
},
"node_modules/esbuild": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz",
"integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==",
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
"integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@ -1749,32 +1749,32 @@
"node": ">=18"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.27.3",
"@esbuild/android-arm": "0.27.3",
"@esbuild/android-arm64": "0.27.3",
"@esbuild/android-x64": "0.27.3",
"@esbuild/darwin-arm64": "0.27.3",
"@esbuild/darwin-x64": "0.27.3",
"@esbuild/freebsd-arm64": "0.27.3",
"@esbuild/freebsd-x64": "0.27.3",
"@esbuild/linux-arm": "0.27.3",
"@esbuild/linux-arm64": "0.27.3",
"@esbuild/linux-ia32": "0.27.3",
"@esbuild/linux-loong64": "0.27.3",
"@esbuild/linux-mips64el": "0.27.3",
"@esbuild/linux-ppc64": "0.27.3",
"@esbuild/linux-riscv64": "0.27.3",
"@esbuild/linux-s390x": "0.27.3",
"@esbuild/linux-x64": "0.27.3",
"@esbuild/netbsd-arm64": "0.27.3",
"@esbuild/netbsd-x64": "0.27.3",
"@esbuild/openbsd-arm64": "0.27.3",
"@esbuild/openbsd-x64": "0.27.3",
"@esbuild/openharmony-arm64": "0.27.3",
"@esbuild/sunos-x64": "0.27.3",
"@esbuild/win32-arm64": "0.27.3",
"@esbuild/win32-ia32": "0.27.3",
"@esbuild/win32-x64": "0.27.3"
"@esbuild/aix-ppc64": "0.28.1",
"@esbuild/android-arm": "0.28.1",
"@esbuild/android-arm64": "0.28.1",
"@esbuild/android-x64": "0.28.1",
"@esbuild/darwin-arm64": "0.28.1",
"@esbuild/darwin-x64": "0.28.1",
"@esbuild/freebsd-arm64": "0.28.1",
"@esbuild/freebsd-x64": "0.28.1",
"@esbuild/linux-arm": "0.28.1",
"@esbuild/linux-arm64": "0.28.1",
"@esbuild/linux-ia32": "0.28.1",
"@esbuild/linux-loong64": "0.28.1",
"@esbuild/linux-mips64el": "0.28.1",
"@esbuild/linux-ppc64": "0.28.1",
"@esbuild/linux-riscv64": "0.28.1",
"@esbuild/linux-s390x": "0.28.1",
"@esbuild/linux-x64": "0.28.1",
"@esbuild/netbsd-arm64": "0.28.1",
"@esbuild/netbsd-x64": "0.28.1",
"@esbuild/openbsd-arm64": "0.28.1",
"@esbuild/openbsd-x64": "0.28.1",
"@esbuild/openharmony-arm64": "0.28.1",
"@esbuild/sunos-x64": "0.28.1",
"@esbuild/win32-arm64": "0.28.1",
"@esbuild/win32-ia32": "0.28.1",
"@esbuild/win32-x64": "0.28.1"
}
},
"node_modules/event-target-shim": {
@ -2001,19 +2001,6 @@
"node": ">= 0.4"
}
},
"node_modules/get-tsconfig": {
"version": "4.13.6",
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz",
"integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==",
"dev": true,
"license": "MIT",
"dependencies": {
"resolve-pkg-maps": "^1.0.0"
},
"funding": {
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
"node_modules/glob-to-regex.js": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz",
@ -2952,16 +2939,6 @@
"node": ">=0.10.0"
}
},
"node_modules/resolve-pkg-maps": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
}
},
"node_modules/retry": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
@ -3264,14 +3241,13 @@
"license": "0BSD"
},
"node_modules/tsx": {
"version": "4.21.0",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
"integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.4.tgz",
"integrity": "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "~0.27.0",
"get-tsconfig": "^4.7.5"
"esbuild": "~0.28.0"
},
"bin": {
"tsx": "dist/cli.mjs"

View File

@ -1,6 +1,6 @@
{
"name": "@salesforce/afv-skills",
"version": "1.25.0",
"version": "1.27.0",
"description": "Salesforce skills for Agentforce Vibes",
"license": "CC-BY-NC-4.0",
"files": [

View File

@ -146,7 +146,7 @@ Do not consider a task complete until all three steps have been run successfully
### Data access (Salesforce)
**Before writing any code that connects to Salesforce, you MUST invoke the `using-ui-bundle-salesforce-data` skill. Do not write any data access code without consulting it first.**
**Before writing any code that connects to Salesforce, you MUST invoke the `experience-ui-bundle-salesforce-data-access` skill. Do not write any data access code without consulting it first.**
This applies to: GraphQL queries/mutations, REST calls, SDK initialization, custom hooks that fetch data, or any code that imports from `@salesforce/platform-sdk`.

View File

@ -146,7 +146,7 @@ Do not consider a task complete until all three steps have been run successfully
### Data access (Salesforce)
**Before writing any code that connects to Salesforce, you MUST invoke the `using-ui-bundle-salesforce-data` skill. Do not write any data access code without consulting it first.**
**Before writing any code that connects to Salesforce, you MUST invoke the `experience-ui-bundle-salesforce-data-access` skill. Do not write any data access code without consulting it first.**
This applies to: GraphQL queries/mutations, REST calls, SDK initialization, custom hooks that fetch data, or any code that imports from `@salesforce/platform-sdk`.

View File

@ -1,159 +0,0 @@
---
name: analyzing-test-failures
description: "Parses a DevOps Center test-failure or Code Analyzer violation payload and explains it in plain language — failure category, offending file/class/method/line, rule violated, and fix direction — then gives prioritized test-improvement suggestions (distinguishing test-code from production-code fixes). Pure reasoning: no system calls or code authoring. TRIGGER when: a test run failed and the user wants root cause; a quality gate failure needs explaining; Code Analyzer violations need translating to plain language; the user shares a failure payload and asks how to address it; tests keep failing and the user wants suggestions; or the user wants to close coverage gaps, strengthen assertions, or fix flaky/weak tests. DO NOT TRIGGER when: the user wants fix code written (use platform-apex-generate) or new test classes authored (use platform-apex-test-generate)."
metadata:
version: "1.0"
minApiVersion: "67.0"
---
# analyzing-test-failures
**Type:** Pure reasoning — no system calls, no code authoring.
**What it does:** Parses a test failure or Code Analyzer violation payload and produces a plain-language explanation, then follows up with concrete, prioritized improvement suggestions per failed test — including whether each fix belongs in the test or in production code. Never exposes raw JSON, stack traces, or API error bodies to the user.
---
## Prerequisites
If you need to fetch the failure payload yourself rather than receiving it, load `checking-devops-prerequisites` first, then use `polling-test-results` to obtain the execution result. If the payload is already in context, no prerequisites are needed — this is pure reasoning.
---
## Inputs
- JSON failure payload provided by the `polling-test-results` skill, or pasted directly into context from a test run or Code Analyzer execution. Specifically required per failed test:
- Test method name
- Failure message (the assertion error or exception text)
- Failure category (assertion failure, unhandled exception, timeout, compile error)
---
## Empty-org / no-data case
If the payload contains no failures or violations, report that clearly (e.g. "No failures found in the provided execution results.") and stop. Do NOT fabricate failures, violations, or improvement suggestions when none are present.
---
## Reasoning steps
1. Determine the failure category:
| Category | Description |
|---|---|
| **Assertion failure** | A test assertion failed (expected vs actual mismatch) |
| **Exception** | An unhandled exception was thrown |
| **Code Analyzer violation** | A static analysis rule was violated (e.g. `ApexCRUDViolation`, `ApexSharingViolations`) |
| **Timeout** | Test exceeded execution time limit |
| **Compile error** | Class failed to compile |
2. For each failure, extract and translate to plain language:
- Offending file and class name
- Method name
- Line number
- What rule or assertion was violated, in plain language
- Suggested fix direction (without writing code)
3. Group failures by category if more than one.
---
## Output format
```text
Test failure summary:
<N> failure(s) found:
1. [<Category>] `<ClassName>.cls``<methodName>()` at line <N>
What happened: <plain-language description>
Rule violated: <ruleName or assertion description>
Fix direction: <plain-language suggestion>
2. [<Category>] `<ClassName2>.cls``<methodName2>()` at line <N>
...
```
---
## Code Analyzer violations
For violations, always include:
- The rule name translated to plain English (e.g. "ApexCRUDViolation" → "A SOQL query was made without checking object-level permissions first")
- The exact line number
- The fix direction (e.g. "Add a `Schema.sObjectType.Account.isAccessible()` check before the query")
---
## Plain-language rule
Never paste raw stack traces, JSON payloads, or internal Salesforce error codes into the output. Always translate to file name, method, line, and plain description.
---
## Suggesting improvements
Invoke this section **after test execution completes with failures**, not on static source code. The failure message is the primary signal — it describes what the test expected vs. what actually happened, which directly informs what the test needs to handle better.
### 1 — Read each failure message
For each failed test in the execution result, extract:
- Test method name
- Failure message (the assertion error or exception message)
- Failure category (assertion failure, unhandled exception, timeout, compile error)
### 2 — Infer what the test is not handling
Reason over the failure message to identify the root cause pattern:
| Failure pattern | Improvement suggestion |
|---|---|
| `NullPointerException` | The test is not handling null input — add a null check or a test setup that ensures the data exists |
| `Assertion failed: expected X but was Y` | The expected value in the assertion is wrong or the test data setup does not produce the right state |
| `List has no rows for assignment` | The test is querying for data that doesn't exist — test setup is incomplete |
| `System.LimitException: Too many SOQL queries` | The test is hitting governor limits — the code under test or test setup is making too many queries |
| `Insufficient access rights on cross-reference id` | The test user lacks the required permissions — the test needs to run as a user with appropriate profile/permission set |
| `DML currently not allowed` | The test is performing DML inside a method called from a context that doesn't allow it |
| Code Analyzer violation message | The production code violates a specific rule — the test exposed it but the fix is in the production code, not the test |
### 3 — Produce actionable suggestions
For each failure, describe in plain language:
- What the failure reveals about what the test is not handling
- What specifically should be added or changed to make the test robust
- Whether the fix is in the **test** (assertion, setup, permissions) or in the **production code** (the test is correct but the code under test is broken)
Do not rewrite the test. Only describe what needs to change and why.
### Output format for improvements
```text
Test improvement suggestions based on execution results:
`<testMethodName>()` — [Assertion Failure / Exception / etc.]
Failure: "<failure message>"
What this reveals: <plain-language explanation>
Suggestion: <specific, actionable recommendation>
Fix location: Test | Production code
`<testMethodName2>()` — [NullPointerException]
Failure: "Attempt to de-reference a null object"
What this reveals: The test is calling the method without setting up the required input data
Suggestion: Add test data setup for <object/field> before calling the method
Fix location: Test
Overall: <N> improvement(s) across <M> failed test(s).
```
### Test fix vs. production-code fix
Suggestions flagged as **Fix location: Production code** indicate a code defect exposed by the test — the test logic itself is sound. These should not block suite promotion on the grounds of test quality; they should be tracked separately as production defects.
Suggestions flagged as **Fix location: Test** indicate the test needs to be hardened — missing setup, wrong assertions, inadequate coverage of edge cases (null inputs, bulk record volumes, mixed permission contexts, governor-limit boundaries).
---
## Related skills
- **`polling-test-results`** — obtains the failure payload that feeds into this skill.
- **`creating-fix-work-item`** — use to create a tracked fix item from the analysis output or to track an approved improvement suggestion as a work item once the user decides to act on it.

View File

@ -1,120 +0,0 @@
---
name: configuring-quality-gate
description: "Creates a DevOps Center quality gate with associated rules (PASS_PERCENTAGE, SEVERITY, ESSENTIAL) and links it to a pipeline-stage suite assignment, after showing a mandatory impact preview and obtaining explicit confirmation. Use this skill when a user wants to set or configure a quality gate, change a coverage threshold, or establish testing benchmarks on a pipeline stage. TRIGGER when: the user wants to set/configure a quality gate, change a coverage threshold, or set testing benchmarks on a stage. DO NOT TRIGGER when: only re-running an existing gate (use running-devops-test-suite in retrigger mode)."
metadata:
version: "1.0"
minApiVersion: "67.0"
---
## Prerequisites
Load `checking-devops-prerequisites` first — Prerequisites 14 AND Prerequisite 5 (stage). You need `doce-org-alias`, `pipelineId`, `stageId`, and the target `DevopsTestSuiteStage` record Id.
## Inputs required
| Input | Source |
|---|---|
| `name` | User-provided name for the quality gate |
| `rules` | List of `{type, threshold?}` — see rule types below |
| `doce-org-alias` | Established in Prereq 1 |
| `testSuiteStageId` | Target `DevopsTestSuiteStage` record Id (Prereq 5) |
## Rule types
| Type | Description | Threshold |
|---|---|---|
| `PASS_PERCENTAGE` | Minimum % of tests that must pass | Required (0100) |
| `SEVERITY` | Maximum allowed severity level of failures | Required (numeric, e.g. 15) |
| `ESSENTIAL` | All essential tests must pass | Not required |
---
## MANDATORY IMPACT PREVIEW
**Before executing any commands**, show the user this preview and wait for explicit confirmation:
> "Here's what this quality gate will enforce on `<stageName>`:
> - Rule: `<type>``<description>`
> - Threshold: `<value>`
> - Affected pipelines: `<list>`
>
> Confirm to apply?"
**Never proceed past this point without showing the impact preview first and receiving explicit confirmation.**
---
## Confirmation gate
Only proceed with the steps below after the user has explicitly confirmed (e.g., "yes", "confirm", "go ahead"). If the user declines or does not confirm, stop and do not execute any commands.
---
## Step 1 — Create the gate record
```bash
sf api request rest \
"/services/data/v67.0/connect/devopstesting/qualityGate" \
--method POST \
--body '{"name": "<gateName>"}' \
--target-org <doce-org-alias>
```
Extract `qualityGateId` from the response.
## Step 2 — Create each rule as a sObject record
Rules are not accepted in the Connect API payload — create them as `DevopsQualityGateRule` records directly. Only create rules the user has requested. `ESSENTIAL` has no threshold.
```bash
sf data create record \
--sobject DevopsQualityGateRule \
--values "DevopsQualityGateId='<qualityGateId>' Rule='PASS_PERCENTAGE' Threshold=<value>" \
--target-org <doce-org-alias> --json
sf data create record \
--sobject DevopsQualityGateRule \
--values "DevopsQualityGateId='<qualityGateId>' Rule='ESSENTIAL'" \
--target-org <doce-org-alias> --json
sf data create record \
--sobject DevopsQualityGateRule \
--values "DevopsQualityGateId='<qualityGateId>' Rule='SEVERITY' Threshold=<value>" \
--target-org <doce-org-alias> --json
```
## Step 3 — Link the gate to the suite stage
Update the `DevopsTestSuiteStage` record to link the new gate:
```bash
sf data update record \
--sobject DevopsTestSuiteStage \
--record-id <testSuiteStageId> \
--values "IsQualityGateEnabled=true DevopsQualityGateId='<qualityGateId>'" \
--target-org <doce-org-alias> --json
```
---
## On success
Confirm to the user:
> "Quality gate `<gateName>` created with `<N>` rule(s) and assigned to `<suiteName>` on `<stageName>`."
## Error handling
Never expose raw API errors. Use the following responses:
| Status | Response |
|---|---|
| 400 | "The quality gate configuration is invalid. Check that all rule types and thresholds are correct." |
| 403 | "You don't have permission to configure quality gates on this org." |
| 500 | "A server error occurred. Try again in a few minutes." |
---
## Related skills
- To re-run a gate after meeting threshold, use `running-devops-test-suite` (retrigger mode).
- To assign or map suites to stages, use `managing-suite-assignments`.

View File

@ -1,113 +0,0 @@
---
name: configuring-test-provider
description: "Configures an available test provider (e.g. Apex Unit Tests, Code Analyzer, Flow Tests, Provar) on a DevOps Center pipeline via the Connect API, after explicit user confirmation, so the provider's test suites become available for assignment to pipeline stages. Takes a pipelineId and a testProviderId. Use this skill when a provider is available on the pipeline but not yet configured and the user wants to enable it. TRIGGER when: the user wants to configure, enable, set up, or add a test provider on a pipeline, or wants a not-yet-configured provider's suites to become available. DO NOT TRIGGER when: re-syncing an already-configured provider to pick up new suites (use syncing-test-providers), or assigning existing suites to a stage (use managing-suite-assignments)."
metadata:
version: "1.0"
minApiVersion: "67.0"
---
# Configuring a Test Provider
Configures an available test provider on a DevOps Center pipeline, making its test suites available for assignment to pipeline stages.
**Confirmation required:** Yes — explicit confirmation before the provider is configured.
## Prerequisites
Load `checking-devops-prerequisites` first — Prerequisites 14 (org login, Agentforce DX plugin, DevOps Center org auth, pipeline identified). Prerequisite 5 (stage) is **not** required: providers are configured at the pipeline level, not the stage level.
| Variable | Source |
|---|---|
| `doce-org-alias` | Established in Prerequisite 1 |
| `pipelineId` | Identified in Prerequisite 4 (pipeline selection) |
| `testProviderId` | Resolved by fetching the pipeline's test providers (below) |
---
## Step 1 — Fetch test providers to resolve the provider ID
Get all test providers for the pipeline so you can resolve the `testProviderId` and confirm which providers are still available to configure:
```bash
sf api request rest \
"/services/data/v67.0/connect/devopstesting/pipeline/<pipelineId>/testProviders?status=all" \
--target-org <doce-org-alias>
```
Each provider entry includes `testProviderId`, `testProviderName`, and a status (Configured vs. Available). Present a short summary grouped by status:
```text
Test providers for <pipelineName>:
✓ Configured:
- Code Analyzer (63 suites)
- Apex Unit Tests (5 suites)
Available (not yet configured):
- Flow Tests
```
- **Only an Available provider can be configured.** If the pipeline has no available providers, report that and stop — do NOT fabricate a provider or ID.
### If the named provider is already Configured
Do **not** present the confirmation gate and do **not** POST to the configure endpoint (Steps 23) — that would create a duplicate `DevopsPipelineTestProvider`. Instead:
1. State plainly that the provider is already configured, including its synced suite count and last-sync time if returned (e.g. *"Flow Tests is already configured on `<pipelineName>` with 3 suites synced (last sync 2026-06-23)."*).
2. Diagnose the user's actual goal and redirect **by name**:
- If the user says the provider's **suites don't appear when assigning tests to a stage**, this is a **stage-assignment gap, not a provider-configuration gap** — the suites already exist at the pipeline level; they just need to be linked to the stage. Redirect to **`managing-suite-assignments`**.
- If the user expects **newly created suites** that aren't yet synced, redirect to **`syncing-test-providers`** (re-sync via `POST /connect/devops/sync`) to pull them in.
3. Do not loop back to configuring — finish cleanly after the explanation and redirect.
## Step 2 — Confirmation gate
**Required — do not call the API before the user confirms.**
> "I'll configure `<testProviderName>` on the `<pipelineName>` pipeline. This will make its suites available for assignment to stages. Confirm?"
Do not proceed until the user gives an affirmative response.
## Step 3 — Configure the provider
On confirmation, call the configure endpoint with the provider ID:
```bash
sf api request rest \
"/services/data/v67.0/connect/devops/pipeline/<pipelineId>/testProvider" \
--method POST \
--body '{"testProviderId": "<testProviderId>"}' \
--target-org <doce-org-alias>
```
## On success
> "Provider `<testProviderName>` is now configured on the `<pipelineName>` pipeline. Its suites are available for assignment to stages."
Newly configured suites can then be assigned to stages with `managing-suite-assignments`.
---
## Critical gotcha
This `POST .../pipeline/<pipelineId>/testProvider` endpoint **creates a new provider configuration record** (`DevopsPipelineTestProvider`). Use it ONLY to configure a provider for the first time. To re-sync an already-configured provider for new suites, use `syncing-test-providers` (`POST /connect/devops/sync`) — calling this configure endpoint on an already-configured provider produces **duplicate** `DevopsPipelineTestProvider` records.
## Error Handling
Never expose raw API error messages, stack traces, or JSON payloads to the user. Map response status codes to plain-language messages:
| Status | User-facing message |
|---|---|
| 400 | "The request was invalid. Check that the provider ID and pipeline ID are correct." |
| 403 | "You don't have permission to configure test providers on this pipeline." |
| 404 | "The pipeline or test provider was not found." |
| 409 | "That provider appears to already be configured on this pipeline. To pick up new suites, re-sync it instead." |
| 500 | "A server error occurred. Try again in a few minutes." |
---
## Related skills
- **`checking-devops-prerequisites`** — loaded first to establish org and pipeline context.
- **`syncing-test-providers`** — once a provider is configured, use this to re-sync it later and pull in newly added suites.
- **`managing-suite-assignments`** — after configuring a provider, use this to assign or map its suites to a pipeline stage.
- **`recommending-devops-tests`** — to recommend which of the newly available suites to run.

View File

@ -0,0 +1,89 @@
---
name: dx-devops-test-failures-analyze
description: "Analyzes DevOps Center test failures and Code Analyzer violations in plain language — failure category, offending file/class/method/line, rule violated, fix direction, and prioritized improvement suggestions (test-code vs production-code) — then optionally creates a tracked fix WorkItem on explicit request. Analysis is pure reasoning; work-item creation is a confirmation-gated write. Use this skill to explain failures or improvement suggestions, translate Code Analyzer violations, or track a fix as a work item. TRIGGER when: a run failed and the user wants root cause; a quality gate failure needs explaining; violations need translating; the user shares a failure payload and asks how to address it; wants to strengthen tests; or wants to create a fix work item, log a remediation, or assign a failure. DO NOT TRIGGER when: the user wants fix code written (use platform-apex-generate) or new test classes authored (use platform-apex-test-generate)."
metadata:
version: "1.0"
minApiVersion: "67.0"
---
# Analyze DevOps Center Test Failures
Parses a test failure or Code Analyzer violation payload, explains it in plain language, produces prioritized improvement suggestions, and — only on explicit user request — creates a tracked fix work item. Parts 12 are pure reasoning (no writes); Part 3 is an optional, confirmation-gated write.
**Never expose raw JSON, stack traces, or internal Salesforce error codes to the user.** Always translate to file name, method, line, and plain description.
---
## Prerequisites
- **Parts 12 (analysis):** If the failure payload is already in context, no prerequisites are needed — this is pure reasoning. If you must fetch the payload yourself, run prerequisites (`references/prerequisite-checks.md`, Prereqs 14) and obtain the execution result via `dx-devops-test-suite-run` (its polling step).
- **Part 3 (work item):** Run Prerequisites 14. You also need a `DevopsProjectId` to file under and an `OwnerId` (assignee). See `references/work-item-creation.md`.
---
## Part 1 — Classify and explain each failure
Determine the failure category, then for each failure extract and translate to plain language: offending file/class, method, line number, the rule or assertion violated, and a fix direction (without writing code). Group failures by category if more than one.
| Category | Description |
|---|---|
| Assertion failure | A test assertion failed (expected vs actual mismatch) |
| Exception | An unhandled exception was thrown |
| Code Analyzer violation | A static-analysis rule was violated (e.g. `ApexCRUDViolation`) |
| Timeout | Test exceeded execution time limit |
| Compile error | Class failed to compile |
**Output format:**
```text
Test failure summary:
<N> failure(s) found:
1. [<Category>] `<ClassName>.cls``<methodName>()` at line <N>
What happened: <plain-language description>
Rule violated: <ruleName or assertion description>
Fix direction: <plain-language suggestion>
```
Full category/pattern tables and Code Analyzer rule translations: `references/failure-categories.md` and `references/code-analyzer-violations.md`.
**Empty / no-data case:** If the payload contains no failures or violations, report that clearly (e.g. "No failures found in the provided execution results.") and stop. Do NOT fabricate failures or suggestions.
---
## Part 2 — Improvement suggestions
Run this **after execution completes with failures**, not on static source. For each failed test, reason over the failure message (the primary signal) to identify what the test is not handling, then produce a specific, actionable suggestion and a **fix location** (Test vs Production code). The full failure-pattern → suggestion mapping is in `references/failure-categories.md`.
```text
Test improvement suggestions based on execution results:
`<testMethodName>()` — [Assertion Failure / Exception / etc.]
Failure: "<failure message>"
What this reveals: <plain-language explanation>
Suggestion: <specific, actionable recommendation>
Fix location: Test | Production code
Overall: <N> improvement(s) across <M> failed test(s).
```
Do not rewrite the test — only describe what needs to change and why. **Fix location: Production code** indicates a code defect exposed by a sound test (track separately, not a test-quality blocker). **Fix location: Test** indicates the test needs hardening (setup, assertions, edge cases).
---
## Part 3 — Create a fix work item (optional, on request only)
Trigger only when the user wants to create a fix work item, log a remediation, or assign a failure to a developer. This is a **write** operation with a mandatory confirmation gate. Follow `references/work-item-creation.md` for inputs, the subject/assignee/project confirmation gate, the `sf data create record --sobject WorkItem` call, and error handling.
> Use `WorkItem` (no namespace) — `DevopsWorkItem` is not a supported sObject in this org version.
If no `DevopsProject` exists in the org, report that the work item cannot be created until a project is set up — do NOT fabricate a project or proceed.
---
## Related skills
- **`dx-devops-test-suite-run`** — produces the failure payload (via its polling step) that feeds this skill.
- **`dx-devops-test-suite-assignments-configure`** — assign/strengthen the suites whose tests are failing.
- **`platform-apex-generate` / `platform-apex-test-generate`** — to actually write fix code or new test classes (out of scope here).

View File

@ -0,0 +1,26 @@
# Code Analyzer Violations
For each Code Analyzer violation, always include:
- The rule name translated to plain English
- The exact line number
- The fix direction (without writing code)
## Rule-name translations (examples)
| Rule name | Plain-language meaning | Fix direction |
|---|---|---|
| `ApexCRUDViolation` | A SOQL query or DML was made without checking object-level permissions first | Add a `Schema.sObjectType.<Object>.isAccessible()` (or `isCreateable`/`isUpdateable`) check before the operation |
| `ApexSharingViolations` | A class that performs data access does not declare sharing enforcement | Add `with sharing` (or an explicit `without sharing` with justification) to the class declaration |
| `ApexDangerousMethods` | A dangerous or disallowed method was used | Replace with the safe, supported alternative |
| `EmptyCatchBlock` | An exception is being swallowed silently | Log or handle the exception rather than leaving the catch block empty |
When a rule isn't in this table, translate it from its name and message into a plain-language description of what was violated, then give the fix direction.
## Plain-language rule
Never paste raw stack traces, JSON payloads, or internal Salesforce error codes into the output. Always translate to file name, method, line, and plain description.
## Fix location for violations
Code Analyzer violations almost always indicate a **production-code** fix — the static-analysis rule is flagging the code under test, not the test itself. Flag these as **Fix location: Production code** and track them separately from test-quality issues.

View File

@ -0,0 +1,85 @@
# Failure Categories & Improvement Mapping
## Inputs required per failed test
- Test method name
- Failure message (the assertion error or exception text)
- Failure category (assertion failure, unhandled exception, timeout, compile error)
## Category table
| Category | Description |
|---|---|
| **Assertion failure** | A test assertion failed (expected vs actual mismatch) |
| **Exception** | An unhandled exception was thrown |
| **Code Analyzer violation** | A static analysis rule was violated (e.g. `ApexCRUDViolation`, `ApexSharingViolations`) |
| **Timeout** | Test exceeded execution time limit |
| **Compile error** | Class failed to compile |
## Per-failure extraction (Part 1)
For each failure, extract and translate to plain language:
- Offending file and class name
- Method name
- Line number
- What rule or assertion was violated, in plain language
- Suggested fix direction (without writing code)
Group failures by category if more than one.
## Failure-pattern → improvement suggestion (Part 2)
Reason over the failure message to identify the root-cause pattern:
| Failure pattern | Improvement suggestion |
|---|---|
| `NullPointerException` | The test is not handling null input — add a null check or a test setup that ensures the data exists |
| `Assertion failed: expected X but was Y` | The expected value in the assertion is wrong or the test data setup does not produce the right state |
| `List has no rows for assignment` | The test is querying for data that doesn't exist — test setup is incomplete |
| `System.LimitException: Too many SOQL queries` | The test is hitting governor limits — the code under test or test setup is making too many queries |
| `Insufficient access rights on cross-reference id` | The test user lacks permissions — run as a user with the appropriate profile/permission set |
| `DML currently not allowed` | The test is performing DML inside a method called from a context that doesn't allow it |
| Code Analyzer violation message | The production code violates a specific rule — the test exposed it, but the fix is in production code, not the test |
## Producing actionable suggestions
For each failure describe, in plain language:
- What the failure reveals about what the test is not handling
- What specifically should be added or changed to make the test robust
- Whether the fix is in the **test** (assertion, setup, permissions) or in **production code** (test is correct, code under test is broken)
Do not rewrite the test — only describe what needs to change and why.
## Test fix vs. production-code fix
- **Fix location: Production code** — a code defect exposed by a sound test. Should NOT block suite promotion on test-quality grounds; track separately as a production defect.
- **Fix location: Test** — the test needs hardening: missing setup, wrong assertions, inadequate coverage of edge cases (null inputs, bulk record volumes, mixed permission contexts, governor-limit boundaries).
## Output formats
**Part 1 — failure summary:**
```text
Test failure summary:
<N> failure(s) found:
1. [<Category>] `<ClassName>.cls``<methodName>()` at line <N>
What happened: <plain-language description>
Rule violated: <ruleName or assertion description>
Fix direction: <plain-language suggestion>
```
**Part 2 — improvement suggestions:**
```text
Test improvement suggestions based on execution results:
`<testMethodName>()` — [Assertion Failure / Exception / etc.]
Failure: "<failure message>"
What this reveals: <plain-language explanation>
Suggestion: <specific, actionable recommendation>
Fix location: Test | Production code
Overall: <N> improvement(s) across <M> failed test(s).
```

View File

@ -1,22 +1,16 @@
---
name: checking-devops-prerequisites
description: "Validate the environment before any DevOps Center pipeline testing action: confirms an authenticated Salesforce org, the Agentforce DX plugin, an authenticated DevOps Center org, and an identified pipeline (and optionally a pipeline stage). Use this FIRST, internally, from any DevOps testing skill (running a test suite, polling results, syncing tests, configuring or retriggering a quality gate, assigning/mapping suites, creating fix work items, recommending tests, explaining coverage, analyzing failures). TRIGGER when another DevOps testing skill needs to confirm org/pipeline context before a query or system call. DO NOT TRIGGER for non-DevOps-Center work."
metadata:
version: "1.0"
minApiVersion: "67.0"
---
# Prerequisite Checks — Shared DevOps Center Gate
# Checking DevOps Prerequisites
Shared gate for every DevOps Center testing skill. Run these checks **before** any query or system call. On any failure, surface the plain-language message and stop until the user resolves it — never proceed to a write with an unverified environment.
Shared environment gate for every DevOps Center testing skill. Run these checks **before** any query or system call. On any failure, surface the plain-language message and stop until the user resolves it — never proceed to a write with an unverified environment.
> **API version:** All DevOps testing system calls target Salesforce API **v67.0** (minimum required).
**Important:** All DevOps Center data (pipelines, stages, test suites, executions) lives in the Salesforce org — NOT in the local repository. Never search the filesystem for pipeline configuration. Always query the org using `sf data query` or `sf api request rest`.
## How other skills use this
**Object model — use the STANDARD objects, never the `sf_devops__` managed package:** DevOps Center testing data lives in standard platform objects — `DevopsPipeline`, `DevopsPipelineStage`, `DevopsPipelineStageTrigger`, `DevopsTestSuite`, `DevopsTestSuiteStage`, `DevopsTestSuiteExecution`, `DevopsProject`, `WorkItem`. Do **NOT** query the legacy managed-package objects (`sf_devops__Pipeline__c`, `sf_devops__Pipeline_Stage__c`, etc.) and do **NOT** gate on a `PackageLicense` / namespace check for `sf_devops`. "DevOps Center installed" is determined **solely** by whether `DevopsPipeline` is queryable and returns records (Prerequisite 4) — never by the presence of the `sf_devops__` namespace. If a `sf_devops__*` object is missing, that is expected and is NOT evidence that DevOps Center is uninstalled.
Every DevOps testing skill loads this skill first and runs Prerequisites 14 in order. Prerequisite 5 (stage) is run **only** when the calling skill operates on a specific pipeline stage (running/retriggering a suite, syncing, configuring a gate, mapping a suite). The calling skill passes back the resolved `doce-org-alias`, `pipelineId`, and (when applicable) `stageId` to use in its own commands.
## How skills use this
Run Prerequisites 14 in order. Prerequisite 5 (stage) is run **only** when the operation targets a specific pipeline stage (configuring a gate, running/retriggering a suite, mapping a suite). Carry forward the resolved `doce-org-alias`, `pipelineId`, and (when applicable) `stageId`.
Resolve the **DevOps Center org alias** without asking the user unless genuinely ambiguous:
1. If the user named an org alias in their message, use it.
@ -94,7 +88,7 @@ sf data query \
## Prerequisite 5 — Pipeline stage identified (conditional)
Run **only** when the calling skill operates on a specific stage.
Run **only** when the operation targets a specific stage (e.g. configuring a quality gate).
If the user's message already names a stage (e.g. "Integration", "Staging", "Production"), use that name directly — do NOT ask again. Look up its Id:
@ -115,27 +109,4 @@ sf data query \
Then ask: "Which pipeline stage are we working with?" — do NOT ask for an org alias; stages are resolved by name from the pipeline.
- **Pass:** stage Id and Name confirmed
- **Deferred:** not required until a calling skill needs it
---
## Error Handling
| Error condition | Response |
|---|---|
| `sf org list` fails entirely | "Could not reach the Salesforce CLI. Make sure `sf` is installed and on your PATH." |
| `sf org display` returns auth error | Surface plain-language re-auth instructions. Do not expose the raw error. |
| `DevopsPipeline` query fails with 5xx | "The DevOps Center org is returning a server error. Try again in a few minutes." |
| Any check throws unexpectedly | "Something went wrong checking prerequisites. Error: [plain summary]. Let's try again — or resolve it manually and let me know when ready." |
Never expose raw API errors, stack traces, or JSON error payloads to the user.
## Gotchas
| Issue | Resolution |
|---|---|
| `DevopsPipeline` query returns empty | DevOps Center not installed on the target org, or wrong org alias — ask the user to verify |
| `DevopsWorkItem` sObject not supported | Use `WorkItem` (no namespace) — the correct API name for this org version |
| Review trigger is pipeline-level, not stage-level | Query `DevopsPipelineStageTrigger` where `TriggerType = 'Review'` and `RelatedRecordId = <pipelineId>` |
| Connect API `testSuites` returns empty with `?stageId=` | Use `?triggerId=<reviewTriggerId>``stageId` only works for stage-level triggers |
| `sf plugins` doesn't match `agentforce` | The installed plugin is `@salesforce/plugin-agent` — match on `plugin-agent` too |
- **Deferred:** not required until the operation needs it

View File

@ -1,14 +1,10 @@
---
name: creating-fix-work-item
description: "Creates a DevOps Center WorkItem to track a fix for a test failure or Code Analyzer violation. Before creating anything, it shows a subject/assignee/project preview and requires explicit confirmation. Use this skill when you want to create a fix work item, track a remediation task, or assign a test or analysis failure to a developer. TRIGGER when: the user wants to create a fix work item, log a remediation, or assign a failure to a developer for resolution. DO NOT TRIGGER when: writing the fix code itself (use platform-apex-generate)."
metadata:
version: "1.0"
minApiVersion: "67.0"
---
# Part 3 — Create a Fix Work Item
Creates a DevOps Center `WorkItem` to track a fix for a test failure or Code Analyzer violation. This is an **optional write**, triggered only when the user asks to create a fix work item, log a remediation, or assign a failure to a developer.
## Prerequisites
Load `checking-devops-prerequisites` first — Prerequisites 14. You need `doce-org-alias`, the `DevopsProjectId` to file under, and an `OwnerId` (assignee). If no DevopsProject exists, surface that the work item cannot be created until a project exists.
Run Prerequisites 14 (`references/prerequisite-checks.md`). You need `doce-org-alias`, a `DevopsProjectId` to file under, and an `OwnerId` (assignee). If no `DevopsProject` exists, surface that the work item cannot be created until a project exists — do NOT fabricate a project or work item.
## Inputs required before creating
@ -16,7 +12,7 @@ Load `checking-devops-prerequisites` first — Prerequisites 14. You need `do
|---|---|
| `DevopsProjectId` | From the pipeline's associated project — query `DevopsProject WHERE Name = '<projectName>'` on the doce org if not already known |
| `Subject` | Derived from failure analysis — e.g. "Fix: Missing code-analyzer-v5.yml workflow in blitz-10-06 repository" |
| `OwnerId` | User ID of the developer to assign to — query `SELECT Id, Name FROM User WHERE Username = '<username>'` on the doce org if not known. Ask the user if the username is unknown. |
| `OwnerId` | User ID of the developer to assign to — query `SELECT Id, Name FROM User WHERE Username = '<username>'` on the doce org if not known. Default to the requesting user when no assignee is specified; ask only if the username is unknown and no default applies. |
| `doce-org-alias` | Established in Prerequisites |
## Confirmation gate
@ -46,7 +42,7 @@ sf data create record \
## On success
Parse the returned `id` from the result and confirm:
Parse the returned `id` and confirm:
> "Fix work item created (`<id>`): `<subject>`. Assigned to `<assigneeName>` in the `<projectName>` project."
@ -61,6 +57,6 @@ Never expose raw API error messages. Map errors to plain-language responses:
| `INSUFFICIENT_ACCESS` | "Your user doesn't have permission to create work items in this project." |
| Any other error | "The work item could not be created. Error: `<plain summary>`. Try again or create it manually in DevOps Center." |
## Related skills
## No-project case
- `analyzing-test-failures` — provides the failure analysis and improvement suggestions that motivate creating a fix work item
If the `DevopsProject` query returns 0 records, report clearly that no DevOps Center project exists and the work item cannot be created until one is set up. Do NOT fabricate a project name/ID, do NOT proceed to the confirmation gate or the create command.

View File

@ -0,0 +1,72 @@
---
name: dx-devops-test-pipeline-configure
description: "Configures DevOps Center pipeline testing infrastructure: enables a test provider so its suites become available, re-syncs a configured provider to pull in new suites, or creates a quality gate with rules on a stage. Routes by intent across three modes after running shared prerequisite checks and an explicit confirmation gate. Use this skill when a user wants to set up, configure, enable, sync, or refresh a test provider, or set/configure a quality gate or coverage threshold on a DevOps Center pipeline stage. TRIGGER when: the user wants to configure/enable/add/set up a test provider, re-sync or refresh a provider's suite list, pull in new suites, or set/configure a quality gate, coverage threshold, or testing benchmark on a stage. DO NOT TRIGGER when: assigning existing suites to a stage (use dx-devops-test-suite-assignments-configure), running or retriggering a suite (use dx-devops-test-suite-run), or non-DevOps-Center work."
metadata:
version: "1.0"
minApiVersion: "67.0"
---
# Configure DevOps Center Pipeline Testing Infrastructure
Sets up and configures a DevOps Center pipeline's testing infrastructure. This skill handles three closely related "configure your pipeline" operations that share the same org context, prerequisites, and entity scope (the pipeline level). Pick the mode that matches the user's intent.
> **API version:** All DevOps testing system calls target Salesforce API **v67.0** (minimum required).
**Important:** All DevOps Center data (pipelines, stages, providers, suites, gates) lives in the Salesforce org — NOT the local repo. Never search the filesystem for pipeline configuration. Always query the org with `sf data query` or `sf api request rest`.
---
## Step 1 — Run prerequisites first (always)
Before any query or system call, run the prerequisite checks in `references/prerequisite-checks.md`. On any failure, surface the plain-language message and stop — never write to an unverified environment.
- **Modes A & B (provider configure/sync):** run Prerequisites 14 (org login, Agentforce DX plugin, DevOps Center org auth, pipeline identified). Prerequisite 5 (stage) is **not** required — providers are configured at the pipeline level.
- **Mode C (quality gate):** run Prerequisites 14 **and** Prerequisite 5 (stage). Prereq 5 gives the `DevopsPipelineStage` only — the target `DevopsTestSuiteStage` record Id is resolved separately in Mode C's Step 0 (trigger → suite-stage row).
Carry forward the resolved `doce-org-alias`, `pipelineId`, and (Mode C) `stageId` / `testSuiteStageId`.
---
## Step 2 — Select the mode
| If the user wants to… | Mode | Follow |
|---|---|---|
| Enable / set up / add a provider that is **not yet configured** | **A — Configure a test provider** | `references/configuring-test-provider.md` |
| Re-sync / refresh an **already-configured** provider to pull in new suites | **B — Sync a configured provider** | `references/syncing-test-providers.md` |
| Set / configure a quality gate, coverage threshold, or testing benchmark on a stage | **C — Configure a quality gate** | `references/configuring-quality-gate.md` |
**Disambiguating A vs B (the critical decision):** First fetch the pipeline's providers (`GET .../testProviders?status=all`) — both modes start there. Then:
- Provider is **Available** (not configured) → **Mode A** (configure).
- Provider is **Configured** but suites are stale/missing → **Mode B** (sync).
- Provider is **Configured** and the user can't see suites *when assigning to a stage* → this is a **stage-assignment gap, not a configuration gap**. Redirect to `dx-devops-test-suite-assignments-configure`.
**Never POST to the configure endpoint for an already-configured provider** — it creates duplicate `DevopsPipelineTestProvider` records. See `references/gotchas.md`.
---
## Step 3 — Confirmation gate (required in every mode)
Every mode mutates org state and **must** show a confirmation gate before any write. Each mode's reference file contains its exact gate wording (Mode C additionally requires a mandatory impact preview before the gate). Do not call any write API until the user gives an affirmative response. If the user declines, stop without writing.
---
## Step 4 — Execute and report
Follow the chosen reference file for the exact API calls, success messages, and error handling:
- `references/configuring-test-provider.md` — Mode A
- `references/syncing-test-providers.md` — Mode B
- `references/configuring-quality-gate.md` — Mode C
- `references/error-handling.md` — consolidated status-code → plain-language tables for all modes
- `references/gotchas.md` — duplicate-provider trap, API-name differences, trigger-type rules
Never expose raw API errors, stack traces, or JSON payloads to the user — always translate to plain language.
---
## Related skills
- **`dx-devops-test-suite-assignments-configure`** — after configuring/syncing a provider, assign or map its suites to a stage; also recommends which suites to run for a commit.
- **`dx-devops-test-suite-run`** — run a suite, or retrigger a quality gate after fixes meet the threshold.
- **`dx-devops-test-failures-analyze`** — explain failures from a run and optionally create a fix work item.

View File

@ -0,0 +1,133 @@
# Mode C — Configure a Quality Gate
Creates a DevOps Center quality gate with associated rules (`PASS_PERCENTAGE`, `SEVERITY`, `ESSENTIAL`) and links it to a pipeline-stage suite assignment, after a mandatory impact preview and explicit confirmation.
## Prerequisites
Run Prerequisites 14 **and** Prerequisite 5 (stage). You need `doce-org-alias`, `pipelineId`, and `stageId`. Prereq 5 resolves only the **`DevopsPipelineStage`** — it does **not** give you the `DevopsTestSuiteStage` record. Resolve that separately in Step 0 below.
## Inputs required
| Input | Source |
|---|---|
| `name` | User-provided name for the quality gate |
| `rules` | List of `{type, threshold?}` — see rule types below |
| `doce-org-alias` | Prerequisite 1 |
| `event` | `Pre-Promote`, `Post-Promote`, or `Review` — which trigger the gate applies to |
| `testSuiteName` | The suite the gate will gate (the gate links to a specific suite-on-stage) |
| `testSuiteStageId` | Target `DevopsTestSuiteStage` record Id — **resolved in Step 0**, not from Prereq 5 |
---
## Step 0 — Resolve the target `DevopsTestSuiteStage` record
A quality gate links to a specific suite assigned to a stage's trigger, represented by a `DevopsTestSuiteStage` record. That object is keyed by `DevopsPipelineStageTriggerId` + `TestSuiteId` (it is **not** linked directly to `DevopsPipelineStage`), so resolve it in two queries.
**0a — Find the stage's trigger for the chosen event:**
```bash
sf data query \
--query "SELECT Id, TriggerType FROM DevopsPipelineStageTrigger WHERE RelatedRecordId = '<stageId>' AND TriggerType = '<event>'" \
--target-org <doce-org-alias> --json
```
> For a `Review` gate the trigger is pipeline-level — use `RelatedRecordId = '<pipelineId>'` with `TriggerType = 'Review'` instead. Record the returned Id as `<triggerId>`.
**0b — Find the suite-stage row for the target suite on that trigger:**
```bash
sf data query \
--query "SELECT Id, TestSuiteId, TestSuite.Name, IsQualityGateEnabled, DevopsQualityGateId FROM DevopsTestSuiteStage WHERE DevopsPipelineStageTriggerId = '<triggerId>'" \
--target-org <doce-org-alias> --json
```
Match the row whose `TestSuite.Name` is the suite the user named; its `Id` is `<testSuiteStageId>`.
- If **no** `DevopsTestSuiteStage` row matches (the suite isn't assigned to that trigger), stop and report it — the suite must be assigned first via `dx-devops-test-suite-assignments-configure`. Do **not** fabricate a `testSuiteStageId` or proceed.
- If the matched row already has `IsQualityGateEnabled = true`, tell the user a gate is already linked and confirm whether to replace it before continuing.
## Rule types
| Type | Description | Threshold |
|---|---|---|
| `PASS_PERCENTAGE` | Minimum % of tests that must pass | Required (0100) |
| `SEVERITY` | Maximum allowed severity level of failures | Required (numeric, e.g. 15) |
| `ESSENTIAL` | All essential tests must pass | Not required |
---
## MANDATORY IMPACT PREVIEW
**Before executing any commands**, show the user this preview and wait for explicit confirmation:
> "Here's what this quality gate will enforce on `<stageName>`:
> - Rule: `<type>``<description>`
> - Threshold: `<value>`
> - Affected pipelines: `<list>`
>
> Confirm to apply?"
**Never proceed past this point without showing the impact preview first and receiving explicit confirmation.**
## Confirmation gate
Only proceed after the user has explicitly confirmed (e.g., "yes", "confirm", "go ahead"). If the user declines or does not confirm, stop and do not execute any commands.
---
## Step 1 — Create the gate record
```bash
sf api request rest \
"/services/data/v67.0/connect/devopstesting/qualityGate" \
--method POST \
--body '{"name": "<gateName>"}' \
--target-org <doce-org-alias>
```
Extract `qualityGateId` from the response.
## Step 2 — Create each rule as an sObject record
Rules are not accepted in the Connect API payload — create them as `DevopsQualityGateRule` records directly. Only create rules the user has requested. `ESSENTIAL` has no threshold.
```bash
sf data create record \
--sobject DevopsQualityGateRule \
--values "DevopsQualityGateId='<qualityGateId>' Rule='PASS_PERCENTAGE' Threshold=<value>" \
--target-org <doce-org-alias> --json
sf data create record \
--sobject DevopsQualityGateRule \
--values "DevopsQualityGateId='<qualityGateId>' Rule='ESSENTIAL'" \
--target-org <doce-org-alias> --json
sf data create record \
--sobject DevopsQualityGateRule \
--values "DevopsQualityGateId='<qualityGateId>' Rule='SEVERITY' Threshold=<value>" \
--target-org <doce-org-alias> --json
```
## Step 3 — Link the gate to the suite stage
Update the `DevopsTestSuiteStage` record to link the new gate:
```bash
sf data update record \
--sobject DevopsTestSuiteStage \
--record-id <testSuiteStageId> \
--values "IsQualityGateEnabled=true DevopsQualityGateId='<qualityGateId>'" \
--target-org <doce-org-alias> --json
```
---
## On success
> "Quality gate `<gateName>` created with `<N>` rule(s) and assigned to `<suiteName>` on `<stageName>`."
## Note
To *re-run* an existing gate after meeting its threshold, that is **not** this mode — use `dx-devops-test-suite-run` (retrigger mode). To assign or map suites to stages first, use `dx-devops-test-suite-assignments-configure`.
See `references/error-handling.md` for status-code responses.

View File

@ -0,0 +1,80 @@
# Mode A — Configure a Test Provider
Configures an *Available* (not-yet-configured) test provider on a DevOps Center pipeline, making its test suites available for assignment to pipeline stages.
**Confirmation required:** Yes — explicit confirmation before the provider is configured.
## Inputs
| Variable | Source |
|---|---|
| `doce-org-alias` | Prerequisite 1 |
| `pipelineId` | Prerequisite 4 (pipeline selection) |
| `testProviderId` | Resolved by fetching the pipeline's test providers (Step 1 below) |
Prerequisite 5 (stage) is **not** required — providers are configured at the pipeline level.
---
## Step 1 — Fetch test providers to resolve the provider ID
```bash
sf api request rest \
"/services/data/v67.0/connect/devopstesting/pipeline/<pipelineId>/testProviders?status=all" \
--target-org <doce-org-alias>
```
Each provider entry includes `testProviderId`, `testProviderName`, and a status (Configured vs. Available). Present a short summary grouped by status:
```text
Test providers for <pipelineName>:
✓ Configured:
- Code Analyzer (63 suites)
- Apex Unit Tests (5 suites)
Available (not yet configured):
- Flow Tests
```
- **Only an Available provider can be configured.** If the pipeline has no available providers, report that and stop — do NOT fabricate a provider or ID.
### If the named provider is already Configured
Do **not** present the confirmation gate and do **not** POST to the configure endpoint (Steps 23) — that would create a duplicate `DevopsPipelineTestProvider`. Instead:
1. State plainly that the provider is already configured, including its synced suite count and last-sync time if returned (e.g. *"Flow Tests is already configured on `<pipelineName>` with 3 suites synced (last sync 2026-06-23)."*).
2. Diagnose the user's actual goal and redirect **by name**:
- If the user says the provider's **suites don't appear when assigning tests to a stage**, this is a **stage-assignment gap, not a provider-configuration gap** — the suites already exist at the pipeline level; they just need to be linked to the stage. Redirect to **`dx-devops-test-suite-assignments-configure`**.
- If the user expects **newly created suites** that aren't yet synced, use **Mode B — Sync a configured provider** (`references/syncing-test-providers.md`) to pull them in.
3. Do not loop back to configuring — finish cleanly after the explanation and redirect.
## Step 2 — Confirmation gate
**Required — do not call the API before the user confirms.**
> "I'll configure `<testProviderName>` on the `<pipelineName>` pipeline. This will make its suites available for assignment to stages. Confirm?"
Do not proceed until the user gives an affirmative response.
## Step 3 — Configure the provider
On confirmation, call the configure endpoint with the provider ID:
```bash
sf api request rest \
"/services/data/v67.0/connect/devops/pipeline/<pipelineId>/testProvider" \
--method POST \
--body '{"testProviderId": "<testProviderId>"}' \
--target-org <doce-org-alias>
```
## On success
> "Provider `<testProviderName>` is now configured on the `<pipelineName>` pipeline. Its suites are available for assignment to stages."
Newly configured suites can then be assigned to stages with `dx-devops-test-suite-assignments-configure`.
---
See `references/gotchas.md` for the duplicate-provider trap and `references/error-handling.md` for status-code responses.

View File

@ -0,0 +1,39 @@
# Error Handling — All Modes
Never expose raw API error messages, stack traces, or JSON payloads to the user. Map response status codes to plain-language messages.
## Mode A — Configure a test provider
| Status | User-facing message |
|---|---|
| 400 | "The request was invalid. Check that the provider ID and pipeline ID are correct." |
| 403 | "You don't have permission to configure test providers on this pipeline." |
| 404 | "The pipeline or test provider was not found." |
| 409 | "That provider appears to already be configured on this pipeline. To pick up new suites, re-sync it instead." |
| 500 | "A server error occurred. Try again in a few minutes." |
## Mode B — Sync a configured provider
| Status | User-facing message |
|---|---|
| 400 | "The sync request was invalid. Check that the provider ID and pipeline ID are correct." |
| 403 | "You don't have permission to sync test providers on this pipeline." |
| 404 | "The pipeline or test provider was not found." |
| 500 | "A server error occurred. Try again in a few minutes." |
## Mode C — Configure a quality gate
| Status | User-facing message |
|---|---|
| 400 | "The quality gate configuration is invalid. Check that all rule types and thresholds are correct." |
| 403 | "You don't have permission to configure quality gates on this org." |
| 500 | "A server error occurred. Try again in a few minutes." |
## Prerequisite / environment errors
| Error condition | Response |
|---|---|
| `sf org list` fails entirely | "Could not reach the Salesforce CLI. Make sure `sf` is installed and on your PATH." |
| `sf org display` returns auth error | Surface plain-language re-auth instructions. Do not expose the raw error. |
| `DevopsPipeline` query fails with 5xx | "The DevOps Center org is returning a server error. Try again in a few minutes." |
| Any check throws unexpectedly | "Something went wrong checking prerequisites. Error: [plain summary]. Let's try again — or resolve it manually and let me know when ready." |

View File

@ -0,0 +1,37 @@
# Critical Gotchas
## Duplicate provider configuration (the big one)
`POST /connect/devops/pipeline/<pipelineId>/testProvider` **creates a new provider configuration record** (`DevopsPipelineTestProvider`). Use it ONLY to configure a provider for the **first time** (Mode A).
To re-sync an already-configured provider for new suites, use `POST /connect/devops/sync` (Mode B). Calling the configure endpoint on an already-configured provider produces **duplicate** `DevopsPipelineTestProvider` records.
**Decision tree:**
- Provider is **Available** → configure via `POST .../pipeline/<id>/testProvider` (Mode A).
- Provider is **Configured**, new suites missing → sync via `POST /connect/devops/sync` (Mode B).
- Provider is **Configured**, suites missing only when assigning to a stage → stage-assignment gap; redirect to `dx-devops-test-suite-assignments-configure`.
## API name differences
| Issue | Resolution |
|---|---|
| `DevopsPipeline` query returns empty | DevOps Center not installed on the target org, or wrong org alias — ask the user to verify |
| `DevopsWorkItem` sObject not supported | Use `WorkItem` (no namespace) — the correct API name for this org version |
| `sf plugins` doesn't match `agentforce` | The installed plugin is `@salesforce/plugin-agent` — match on `plugin-agent` too |
## Trigger-type rules
| Issue | Resolution |
|---|---|
| Review trigger is pipeline-level, not stage-level | Query `DevopsPipelineStageTrigger` where `TriggerType = 'Review'` and `RelatedRecordId = <pipelineId>` |
| Connect API `testSuites` returns empty with `?stageId=` | Use `?triggerId=<reviewTriggerId>``stageId` only works for stage-level triggers |
## Endpoint families
- **Configure provider:** `POST /connect/devops/pipeline/<pipelineId>/testProvider`
- **Sync provider:** `POST /connect/devops/sync`
- **List providers:** `GET /connect/devopstesting/pipeline/<pipelineId>/testProviders?status=all`
- **Quality gate:** `POST /connect/devopstesting/qualityGate`
Note the `devops` vs `devopstesting` path segment differs between sync/configure and the listing/quality-gate endpoints — copy them exactly.

View File

@ -0,0 +1,112 @@
# Prerequisite Checks — Shared DevOps Center Gate
Shared environment gate for every DevOps Center testing skill. Run these checks **before** any query or system call. On any failure, surface the plain-language message and stop until the user resolves it — never proceed to a write with an unverified environment.
> **API version:** All DevOps testing system calls target Salesforce API **v67.0** (minimum required).
**Important:** All DevOps Center data (pipelines, stages, test suites, executions) lives in the Salesforce org — NOT in the local repository. Never search the filesystem for pipeline configuration. Always query the org using `sf data query` or `sf api request rest`.
**Object model — use the STANDARD objects, never the `sf_devops__` managed package:** DevOps Center testing data lives in standard platform objects — `DevopsPipeline`, `DevopsPipelineStage`, `DevopsPipelineStageTrigger`, `DevopsTestSuite`, `DevopsTestSuiteStage`, `DevopsTestSuiteExecution`, `DevopsProject`, `WorkItem`. Do **NOT** query the legacy managed-package objects (`sf_devops__Pipeline__c`, `sf_devops__Pipeline_Stage__c`, etc.) and do **NOT** gate on a `PackageLicense` / namespace check for `sf_devops`. "DevOps Center installed" is determined **solely** by whether `DevopsPipeline` is queryable and returns records (Prerequisite 4) — never by the presence of the `sf_devops__` namespace. If a `sf_devops__*` object is missing, that is expected and is NOT evidence that DevOps Center is uninstalled.
## How skills use this
Run Prerequisites 14 in order. Prerequisite 5 (stage) is run **only** when the operation targets a specific pipeline stage (configuring a gate, running/retriggering a suite, mapping a suite). Carry forward the resolved `doce-org-alias`, `pipelineId`, and (when applicable) `stageId`.
Resolve the **DevOps Center org alias** without asking the user unless genuinely ambiguous:
1. If the user named an org alias in their message, use it.
2. Otherwise, use the default org (`sf org display --json`, no `--target-org`).
3. Only if the default org has no `DevopsPipeline` records (Prereq 4 fails), ask: "Which org alias is your DevOps Center org?"
---
## Prerequisite 1 — Salesforce org: active login
```bash
sf org list --json
```
Look for at least one entry in `result.nonScratchOrgs`, `result.scratchOrgs`, or `result.sandboxes` with `"connectedStatus": "Connected"`.
- **Pass:** at least one org is Connected
- **Fail:** no orgs listed, or all show a non-connected status
**On fail:** "No authenticated Salesforce org found. Run `sf org login web --alias <your-alias>` in your terminal, then come back."
---
## Prerequisite 2 — Agentforce DX plugin installed
```bash
sf plugins --json
```
Look for a plugin entry whose `name` contains `plugin-agent`, `agentforce`, or `einstein` (case-insensitive).
- **Pass:** plugin found
- **Fail:** no matching entry
**On fail:** "The Agentforce DX Plugin is not installed. Run `sf plugins install @salesforce/plugin-agent`, then restart the IDE and try again."
---
## Prerequisite 3 — DevOps Center org authenticated
```bash
sf org display --target-org <doce-org-alias> --json
```
Check that `"connectedStatus"` is `"Connected"`.
- **Pass:** Connected
- **Fail:** expired session or error
**On fail:** "Your DevOps Center org session has expired. Run `sf org login web --alias <doce-org-alias>` to re-authenticate."
---
## Prerequisite 4 — Pipeline identified
```bash
sf data query \
--query "SELECT Id, Name, CreatedDate FROM DevopsPipeline ORDER BY Name ASC" \
--target-org <doce-org-alias> \
--json
```
- **Pass (exactly one):** use it automatically — do NOT ask.
- **Pass (multiple):** if the user already named a pipeline, match by name. Otherwise display a numbered list and ask:
```text
Found <N> pipelines:
1. <Name>
2. <Name>
Which pipeline would you like to work with?
```
- **Fail (no records):** "No DevOps Center pipeline found. Create a project and pipeline in DevOps Center before using the DevOps Testing Skills."
- **Fail (unsupported object):** "DevOps Center does not appear to be installed on `<doce-org-alias>`. Check that you're pointing at the correct org."
---
## Prerequisite 5 — Pipeline stage identified (conditional)
Run **only** when the operation targets a specific stage (e.g. configuring a quality gate).
If the user's message already names a stage (e.g. "Integration", "Staging", "Production"), use that name directly — do NOT ask again. Look up its Id:
```bash
sf data query \
--query "SELECT Id, Name FROM DevopsPipelineStage WHERE DevopsPipelineId = '<pipelineId>' AND Name = '<stageName>'" \
--target-org <doce-org-alias> --json
```
Only if no stage is mentioned, fetch the full list and ask which one:
```bash
sf data query \
--query "SELECT Id, Name FROM DevopsPipelineStage WHERE DevopsPipelineId = '<pipelineId>' ORDER BY Name ASC" \
--target-org <doce-org-alias> --json
```
Then ask: "Which pipeline stage are we working with?" — do NOT ask for an org alias; stages are resolved by name from the pipeline.
- **Pass:** stage Id and Name confirmed
- **Deferred:** not required until the operation needs it

View File

@ -0,0 +1,69 @@
# Mode B — Sync a Configured Provider
Re-syncs an already-*Configured* test provider on a DevOps Center pipeline so that suites added to the provider since it was last configured become available for assignment to stages.
**Confirmation required:** Yes — explicit confirmation before the sync is triggered.
## Inputs
| Variable | Source |
|---|---|
| `doce-org-alias` | Prerequisite 1 |
| `pipelineId` | Prerequisite 4 (pipeline selection) |
| `testProviderId` | Resolved by fetching the pipeline's test providers (Step 1 below) |
Prerequisite 5 (stage) is **not** required — providers are synced at the pipeline level.
---
## Step 1 — Fetch test providers to resolve the provider ID
```bash
sf api request rest \
"/services/data/v67.0/connect/devopstesting/pipeline/<pipelineId>/testProviders?status=all" \
--target-org <doce-org-alias>
```
Each provider entry includes `testProviderId`, `testProviderName`, and a status (Configured vs. Available). Present a short summary grouped by status (same format as Mode A).
- **Only a Configured provider can be synced.** If the user names an *Available* (not-yet-configured) provider, explain it must be configured first — use **Mode A** (`references/configuring-test-provider.md`).
- If the pipeline has no configured providers, report that and stop — do NOT fabricate a provider or ID.
## Step 2 — Confirmation gate
**Required — do not call the API before the user confirms.**
> "I'll re-sync `<testProviderName>` on the `<pipelineName>` pipeline to pick up any new suites. Confirm?"
Do not proceed until the user gives an affirmative response.
## Step 3 — Trigger the sync
On confirmation, call the sync endpoint with the provider ID(s) and pipeline ID:
```bash
sf api request rest \
"/services/data/v67.0/connect/devops/sync" \
--method POST \
--body '{
"testProviderIds": ["<testProviderId>"],
"pipelineId": "<pipelineId>"
}' \
--target-org <doce-org-alias>
```
`testProviderIds` is a list — multiple configured providers can be synced in one call.
## On success
> "Provider `<testProviderName>` sync started. The operation is running asynchronously — new suites will be available shortly."
The sync runs asynchronously; newly synced suites can then be assigned to stages with `dx-devops-test-suite-assignments-configure`.
---
## Critical gotcha
**Do NOT use** `POST /connect/devops/pipeline/<pipelineId>/testProvider` to sync — that endpoint **creates a new provider configuration** and will result in duplicate `DevopsPipelineTestProvider` records. Sync only via `POST /connect/devops/sync`. See `references/gotchas.md`.
See `references/error-handling.md` for status-code responses.

View File

@ -0,0 +1,74 @@
---
name: dx-devops-test-suite-assignments-configure
description: "Recommends and manages DevOps Center test suite assignments for pipeline stages. Mode A analyzes a commit diff against assigned suite metadata to recommend relevant existing suites and flag coverage gaps (pure reasoning). Modes B-D assign a single suite, bulk-map multiple suites with a mandatory impact preview, or add/remove test classes with governance rules, via the testSuiteStages Connect API. Use this skill to recommend suites for a commit, assign or map suites to stages, or add/remove tests in a suite. TRIGGER when: the user asks which suites to run for a commit/diff or what covers their changes; a suite is unlinked and the user wants it assigned; the user wants to configure suite-to-stage mappings, assign multiple suites, or add/remove/sync tests in a suite. DO NOT TRIGGER when: configuring or syncing a test provider (use dx-devops-test-pipeline-configure), running suites (use dx-devops-test-suite-run), or authoring/running tests directly (use platform-apex-test-generate or platform-apex-test-run)."
metadata:
version: "1.0"
minApiVersion: "67.0"
---
# Configure DevOps Center Suite Assignments
Recommends which existing test suites to run for a change, and manages how suites are assigned and mapped to pipeline stages. These operations share the same suite-stage metadata: a recommendation surfaces relevant suites and flags gaps, and those gaps lead directly into assignment.
> **API version:** All DevOps testing system calls target Salesforce API **v67.0** (minimum required).
**Important:** All DevOps Center data lives in the Salesforce org — NOT the local repo. Never search the filesystem for suite configuration. Always query the org with `sf data query` or `sf api request rest`.
---
## Step 1 — Run prerequisites first (always)
Run the prerequisite checks in `references/prerequisite-checks.md` before any query or system call. On any failure, surface the plain-language message and stop.
- **Mode A (recommend):** Prerequisites 14 (org login, plugin, DevOps Center org auth, pipeline identified). No stage required — recommendation reads the pipeline-level Review trigger.
- **Modes BD (assign/map/classes):** Prerequisites 14 **and** Prerequisite 5 (stage). You need `doce-org-alias`, `pipelineId`, and `stageId`.
---
## Step 2 — Select the mode
| If the user wants to… | Mode | Follow |
|---|---|---|
| Know **which suites to run** for a commit/diff, or what covers their changes | **A — Recommend suites** | `references/recommendation-logic.md` |
| Assign **one** suite to a stage as a one-off | **B — Assign a single suite** | `references/suite-assignment-modes.md` |
| **Bulk-map** multiple suites to a stage as a testing strategy | **C — Map multiple suites** | `references/suite-assignment-modes.md` |
| **Add/remove** individual test classes within a suite assignment | **D — Add/remove classes** | `references/suite-assignment-modes.md` |
Mode A is pure reasoning (no writes). Modes BD mutate org state via the same `testSuiteStages` endpoint (`references/api-endpoint.md`).
**How A feeds BD:** When recommendation flags a relevant suite that is *not assigned* to the stage, that gap is the input to Mode B/C. When it flags a *new method with no suite coverage*, direct the developer to author tests manually (v1 constraint — never suggest generating tests here).
---
## Step 3 — Governance & confirmation (Modes BD)
Modes BD **must** confirm before any write:
- **Mode B** — single confirmation prompt naming the suite, stage, and event.
- **Mode C** — a **mandatory impact-preview table** (Suite / Stage / Event / Action) before the confirmation gate.
- **Mode D** — re-present the final test list before confirming. **Rejected tests must be EXCLUDED from the payload.** If tests were modified during review, re-present the final list before requesting confirmation. Never call without explicit approval.
Do not call the API until the user gives an affirmative response. If the user declines, stop without writing. Full wording for each gate is in `references/suite-assignment-modes.md`.
Mode A (recommendation) makes no writes and needs no confirmation gate.
---
## Step 4 — Execute and report
Follow the chosen reference file:
- `references/recommendation-logic.md` — Mode A: diff classification, provider matching, ranking, gap flagging, output format.
- `references/suite-assignment-modes.md` — Modes BD: inputs, confirmation wording, success messages.
- `references/api-endpoint.md` — the shared `testSuiteStages` POST payload schema (Modes BD).
- `references/error-handling.md` — status-code → plain-language tables.
Never expose raw API errors, stack traces, or JSON to the user.
---
## Related skills
- **`dx-devops-test-pipeline-configure`** — if the suite you want to assign doesn't appear yet, configure or re-sync the provider; also configures quality gates on a stage after mapping.
- **`dx-devops-test-suite-run`** — execute a recommended/assigned suite on a stage.
- **`dx-devops-test-failures-analyze`** — analyze failures and improvement suggestions for the tests within a suite.

View File

@ -0,0 +1,30 @@
# API Endpoint — testSuiteStages (Modes BD)
All three assignment modes (B, C, D) use the same Connect API endpoint. Substitute all `<placeholder>` values before executing.
```bash
sf api request rest "/services/data/v67.0/connect/devopstesting/pipeline/<pipelineId>/testSuiteStages" --method POST --body '{"pipelineStageId":"<stageId>","event":"<event>","assignments":[{"testSuiteId":"<id>","action":"add|remove"}]}' --target-org <doce-org-alias>
```
## Full payload schema
```json
{
"pipelineStageId": "<stageId>",
"event": "<event>",
"assignments": [
{"testSuiteId": "<suiteId1>", "action": "add"},
{"testSuiteId": "<suiteId2>", "action": "remove"}
]
}
```
| Field | Type | Description |
|---|---|---|
| `pipelineStageId` | string | The pipeline stage ID (from Prerequisite 5) |
| `event` | string | `Pre-Promote`, `Post-Promote`, or `Review` |
| `assignments` | array | One or more `{testSuiteId, action}` entries — `action` is `add` or `remove` |
- **Mode B** sends a single `add` assignment.
- **Mode C** sends multiple `add`/`remove` entries in one call (bulk mapping).
- **Mode D** sends `add`/`remove` entries for the classes/suites being synced — rejected tests excluded.

View File

@ -0,0 +1,14 @@
# Error Handling — Suite Assignments (Modes BD)
Never expose raw API error messages, stack traces, or JSON payloads to the user. Map response status codes to plain-language messages.
| Status | User-facing message |
|---|---|
| 400 | "The request was invalid. Check that all suite and stage IDs are correct and the event type is valid." |
| 403 | "You don't have permission to modify suite assignments on this pipeline." |
| 404 | "The pipeline or stage was not found." |
| 500 | "A server error occurred. Try again in a few minutes." |
## Mode A (recommendation) errors
Mode A makes only read queries. If a `sf data query` fails, report the problem in plain language and stop — do NOT fabricate suite names, recommendations, or coverage data. If no suites are assigned to the Review trigger, state that explicitly ("No test suites are currently assigned to the Review trigger for this pipeline").

View File

@ -0,0 +1,112 @@
# Prerequisite Checks — Shared DevOps Center Gate
Shared environment gate for every DevOps Center testing skill. Run these checks **before** any query or system call. On any failure, surface the plain-language message and stop until the user resolves it — never proceed to a write with an unverified environment.
> **API version:** All DevOps testing system calls target Salesforce API **v67.0** (minimum required).
**Important:** All DevOps Center data (pipelines, stages, test suites, executions) lives in the Salesforce org — NOT in the local repository. Never search the filesystem for pipeline configuration. Always query the org using `sf data query` or `sf api request rest`.
**Object model — use the STANDARD objects, never the `sf_devops__` managed package:** DevOps Center testing data lives in standard platform objects — `DevopsPipeline`, `DevopsPipelineStage`, `DevopsPipelineStageTrigger`, `DevopsTestSuite`, `DevopsTestSuiteStage`, `DevopsTestSuiteExecution`, `DevopsProject`, `WorkItem`. Do **NOT** query the legacy managed-package objects (`sf_devops__Pipeline__c`, `sf_devops__Pipeline_Stage__c`, etc.) and do **NOT** gate on a `PackageLicense` / namespace check for `sf_devops`. "DevOps Center installed" is determined **solely** by whether `DevopsPipeline` is queryable and returns records (Prerequisite 4) — never by the presence of the `sf_devops__` namespace. If a `sf_devops__*` object is missing, that is expected and is NOT evidence that DevOps Center is uninstalled.
## How skills use this
Run Prerequisites 14 in order. Prerequisite 5 (stage) is run **only** when the operation targets a specific pipeline stage (configuring a gate, running/retriggering a suite, mapping a suite). Carry forward the resolved `doce-org-alias`, `pipelineId`, and (when applicable) `stageId`.
Resolve the **DevOps Center org alias** without asking the user unless genuinely ambiguous:
1. If the user named an org alias in their message, use it.
2. Otherwise, use the default org (`sf org display --json`, no `--target-org`).
3. Only if the default org has no `DevopsPipeline` records (Prereq 4 fails), ask: "Which org alias is your DevOps Center org?"
---
## Prerequisite 1 — Salesforce org: active login
```bash
sf org list --json
```
Look for at least one entry in `result.nonScratchOrgs`, `result.scratchOrgs`, or `result.sandboxes` with `"connectedStatus": "Connected"`.
- **Pass:** at least one org is Connected
- **Fail:** no orgs listed, or all show a non-connected status
**On fail:** "No authenticated Salesforce org found. Run `sf org login web --alias <your-alias>` in your terminal, then come back."
---
## Prerequisite 2 — Agentforce DX plugin installed
```bash
sf plugins --json
```
Look for a plugin entry whose `name` contains `plugin-agent`, `agentforce`, or `einstein` (case-insensitive).
- **Pass:** plugin found
- **Fail:** no matching entry
**On fail:** "The Agentforce DX Plugin is not installed. Run `sf plugins install @salesforce/plugin-agent`, then restart the IDE and try again."
---
## Prerequisite 3 — DevOps Center org authenticated
```bash
sf org display --target-org <doce-org-alias> --json
```
Check that `"connectedStatus"` is `"Connected"`.
- **Pass:** Connected
- **Fail:** expired session or error
**On fail:** "Your DevOps Center org session has expired. Run `sf org login web --alias <doce-org-alias>` to re-authenticate."
---
## Prerequisite 4 — Pipeline identified
```bash
sf data query \
--query "SELECT Id, Name, CreatedDate FROM DevopsPipeline ORDER BY Name ASC" \
--target-org <doce-org-alias> \
--json
```
- **Pass (exactly one):** use it automatically — do NOT ask.
- **Pass (multiple):** if the user already named a pipeline, match by name. Otherwise display a numbered list and ask:
```text
Found <N> pipelines:
1. <Name>
2. <Name>
Which pipeline would you like to work with?
```
- **Fail (no records):** "No DevOps Center pipeline found. Create a project and pipeline in DevOps Center before using the DevOps Testing Skills."
- **Fail (unsupported object):** "DevOps Center does not appear to be installed on `<doce-org-alias>`. Check that you're pointing at the correct org."
---
## Prerequisite 5 — Pipeline stage identified (conditional)
Run **only** when the operation targets a specific stage (e.g. configuring a quality gate).
If the user's message already names a stage (e.g. "Integration", "Staging", "Production"), use that name directly — do NOT ask again. Look up its Id:
```bash
sf data query \
--query "SELECT Id, Name FROM DevopsPipelineStage WHERE DevopsPipelineId = '<pipelineId>' AND Name = '<stageName>'" \
--target-org <doce-org-alias> --json
```
Only if no stage is mentioned, fetch the full list and ask which one:
```bash
sf data query \
--query "SELECT Id, Name FROM DevopsPipelineStage WHERE DevopsPipelineId = '<pipelineId>' ORDER BY Name ASC" \
--target-org <doce-org-alias> --json
```
Then ask: "Which pipeline stage are we working with?" — do NOT ask for an org alias; stages are resolved by name from the pipeline.
- **Pass:** stage Id and Name confirmed
- **Deferred:** not required until the operation needs it

View File

@ -1,28 +1,18 @@
---
name: recommending-devops-tests
description: "Analyzes a commit diff and available DevOps Center test suite metadata to recommend the most relevant existing test suites, then flags coverage gaps where no suite covers a new method — via pure reasoning, no system calls beyond the prerequisite queries. Use this skill when a developer wants to know which test suites to run for a specific commit or diff, what tests cover their changes, or wants suite recommendations at commit time. TRIGGER when: the user asks which test suites to run for a commit/diff, asks what tests cover their changes, or asks for suite recommendations before promoting. DO NOT TRIGGER when: authoring new tests (use platform-apex-test-generate) or running sf apex run test directly (use platform-apex-test-run)."
metadata:
version: "1.0"
minApiVersion: "67.0"
---
# Mode A — Recommend Suites for a Commit/Diff
# Recommending DevOps Tests
**Type:** Pure reasoning — no system calls beyond the prerequisite data-fetch queries documented below.
**Type:** Pure reasoning — no system calls beyond the prerequisite data-fetch queries documented below. No writes.
**What it does:** Analyzes the commit diff and available suite metadata to recommend the most relevant existing test suites assigned to the Review pipeline stage. Flags coverage gaps where no suite covers a new method.
---
## Prerequisites
Load and follow the `checking-devops-prerequisites` skill first (Prerequisites 14). This skill needs a confirmed DevOps Center org alias and pipeline Id before it can proceed.
Run Prerequisites 14 (`references/prerequisite-checks.md`). A confirmed DevOps Center org alias and `pipelineId` are required before proceeding. No stage prompt — recommendation reads the pipeline-level Review trigger.
---
## Step 1 — Fetch suite metadata
Before reasoning can begin, fetch the test suite metadata assigned to the Review pipeline stage. This requires two queries.
Two queries are required before reasoning.
**1a — Find the Review pipeline stage trigger:**
@ -48,9 +38,7 @@ Each row provides: `TestSuiteId`, `TestSuite.Name`, `IsQualityGateEnabled`, and
> Note: Do NOT use the beta `/connect/devops/.../testSuites` endpoint — it returns empty results. Query `DevopsTestSuiteStage` directly as shown above.
Never expose raw API errors or raw JSON to the user. If a query fails, report the problem in plain language and stop.
The commit diff comes from the user or surrounding context.
Never expose raw API errors or raw JSON to the user. If a query fails, report the problem in plain language and stop. The commit diff comes from the user or surrounding context.
---
@ -58,8 +46,6 @@ The commit diff comes from the user or surrounding context.
### 1 — Classify the diff by change type
Parse the diff file extensions and paths to determine what types of changes were made:
| File pattern | Change type |
|---|---|
| `*.cls`, `*.trigger` | Apex |
@ -71,7 +57,7 @@ A single commit may contain multiple change types. Identify all of them.
### 2 — Map change types to test providers
For each change type identified, match against the `testProviderName` of the fetched suites:
For each change type, match against the `testProviderName` of the fetched suites:
| Change type | Match suites whose `testProviderName` contains |
|---|---|
@ -81,7 +67,7 @@ For each change type identified, match against the `testProviderName` of the fet
| LWC / JavaScript | `LWC` or `JavaScript` |
| Code Analyzer (any) | `Code Analyzer` — then sub-filter by suite name convention: `recommended` → Apex/general rules (suggest for Apex and Java changes), `html` → suggest for HTML/LWC template changes, `css` → suggest for CSS changes. If no suite name matches the convention, suggest all Code Analyzer suites and note the ambiguity. |
Only recommend suites whose provider matches at least one change type in the diff. Suites from non-matching providers are excluded from the recommendation.
Only recommend suites whose provider matches at least one change type in the diff. Suites from non-matching providers are excluded.
### 3 — Rank matched suites
@ -129,9 +115,7 @@ Coverage gaps (new methods — manual authoring required):
Only recommend existing suites. Never suggest generating new tests. If gaps exist, direct the developer to author tests manually and explain exactly which methods need coverage.
---
## How recommendations feed assignment
## Related skills
- To analyze failures from a run, use `analyzing-test-failures`.
- To actually execute a recommended suite, use `running-devops-test-suite`.
- A relevant suite that exists but is **not assigned** to the stage → use **Mode B/C** (`references/suite-assignment-modes.md`) to assign it.
- To actually execute a recommended suite, use **`dx-devops-test-suite-run`**.

View File

@ -0,0 +1,99 @@
# Modes BD — Assign / Map / Manage Suite Classes
All three modes use the same `testSuiteStages` endpoint (`references/api-endpoint.md`). They differ in scope and the confirmation pattern required.
## Prerequisites & shared inputs
Run Prerequisites 14 **and** Prerequisite 5 (stage). You need:
| Variable | Description |
|---|---|
| `doce-org-alias` | Prerequisite 1 |
| `pipelineId` | Prerequisite 4 (pipeline selection) |
| `stageId` | Prerequisite 5 (stage selection) |
| `event` | `Pre-Promote`, `Post-Promote`, or `Review` |
---
## Mode B — Assign a single suite to a stage
Use when a relevant test suite already exists but is not yet linked to a stage and the user wants to add it as a single one-off assignment.
**Additional inputs:**
| Variable | Description |
|---|---|
| `testSuiteId` | ID of the suite to assign |
| `testSuiteName` | Name of the suite (for display in confirmation) |
**Confirmation gate (required before any API call):**
> "The suite `<testSuiteName>` is not currently assigned to the `<stageName>` stage (`<event>`). Would you like me to assign it now?"
Do not proceed until the user confirms.
**On success:**
> "Suite `<testSuiteName>` has been assigned to the `<stageName>` stage (`<event>`)."
---
## Mode C — Map multiple suites to a stage
Use when configuring suite-to-stage mappings across a pipeline or assigning multiple suites as part of a testing strategy.
**Additional inputs:**
| Input | Description |
|---|---|
| `testSuiteOperations` | List of `{testSuiteId, action: "add"\|"remove"}` |
**MANDATORY IMPACT PREVIEW — required before any changes.** Do not call the API until the user has confirmed the preview:
> "Here's the suite mapping I'll apply:
>
> | Suite | Stage | Event | Action |
> |---|---|---|---|
> | `<suiteName>` | `<stageName>` | `<event>` | Add |
> | `<suiteName2>` | `<stageName>` | `<event>` | Remove |
>
> Confirm to apply all changes?"
Only proceed after the user explicitly confirms.
**On success:**
> "Suite mapping applied. `<N>` suite(s) updated for the `<stageName>` stage."
---
## Mode D — Add/remove test classes in a suite
Use when the user wants to add or remove individual test classes within an existing suite assignment, sync reviewed tests into a suite, or promote tests to a suite.
**Additional inputs:**
| Input | Source |
|---|---|
| `testSuiteOperations` | List of `{testSuiteId, action: "add"\|"remove"}` |
**Governance rules:**
- **Never call this without explicit approval.** AI-reviewed or modified tests must be re-presented to the user before this call is made.
- Rejected tests must be EXCLUDED from the payload — do not include them even if they were previously in the suite.
- If tests were modified during review, re-present the final list before requesting confirmation.
**Confirmation gate (required — do not skip):**
> "I'm about to sync the following changes to the test suite:
> - **Add:** `<testSuiteName1>`, `<testSuiteName2>`
> - **Remove:** `<testSuiteName3>`
> - Stage: `<stageName>` | Event: `<event>`
>
> Confirm?"
Only proceed after explicit confirmation.
**On success:**
> "Test suite updated successfully for the `<stageName>` stage."

View File

@ -0,0 +1,111 @@
---
name: dx-devops-test-suite-run
description: "Runs DevOps Center test suites on a pipeline stage (Pre-Promote, Post-Promote, or Review event) end to end: triggers async execution via the Connect API after an explicit confirmation gate, then polls by runId at provider-specific intervals until it completes, fails, or times out, and hands results to failure analysis. Also retriggers a quality gate after fixes, but only once coverage meets the threshold. Use this skill when a user wants to run, kick off, or launch test suites on a stage, re-run a quality gate, or watch an in-progress run to completion. TRIGGER when: the user wants to run/launch suites on a stage, execute tests before or after promotion, re-run a quality gate after fixing failures, unblock a blocked promotion after adding tests, or poll/watch an in-progress run. DO NOT TRIGGER when: running sf apex run test directly (use platform-apex-test-run), or configuring a NEW gate or threshold (use dx-devops-test-pipeline-configure)."
metadata:
version: "1.0"
minApiVersion: "67.0"
---
# Run a DevOps Center Test Suite
Triggers a DevOps Center test suite execution and watches it to completion. Running and polling are two halves of one operation — never poll without first having (or being handed) a `runId`.
> **API version:** All DevOps testing system calls target Salesforce API **v67.0** (minimum required).
**Important:** All DevOps Center data lives in the Salesforce org — NOT the local repo. Always query the org with `sf data query` or `sf api request rest`.
---
## Prerequisites
Run the prerequisite checks in `references/prerequisite-checks.md` — Prerequisites 14 **and** Prerequisite 5 (stage), since this skill operates on a specific stage. You need the confirmed `doce-org-alias`, `pipelineId`, and `stageId`.
## Inputs required
| Input | How to obtain |
|---|---|
| `pipelineId` | Prerequisite 4 (pipeline selection) |
| `stageId` | Prerequisite 5 (pipeline stage confirmation) |
| `event` | Confirm with user: `Pre-Promote`, `Post-Promote`, or `Review` |
| `testSuiteIds` | Confirmed suite IDs from selection or recommendation |
| `doce-org-alias` | Prerequisite 1 |
---
## Step 1 — Trigger execution
### Confirmation gate
**This call mutates org state — do not proceed without explicit user confirmation.** Before calling the API, show:
> "I'm about to run tests with the following configuration:
> - Pipeline: `<pipelineName>`
> - Stage: `<stageName>`
> - Event: `<event>`
> - Suite(s): `<suiteName(s)>`
> - Org: `<doce-org-alias>`
>
> Shall I proceed?"
Do not make the API call until the user confirms.
### API call
```bash
sf api request rest \
"/services/data/v67.0/connect/devopstesting/pipeline/<pipelineId>/stage/execute" \
--method POST \
--body '{
"stageId": "<stageId>",
"event": "<event>",
"testSuiteIds": ["<suiteId1>", "<suiteId2>"]
}' \
--target-org <doce-org-alias>
```
| Field | Type | Description |
|---|---|---|
| `stageId` | string | The ID of the pipeline stage to execute tests on |
| `event` | string | `Pre-Promote`, `Post-Promote`, or `Review` |
| `testSuiteIds` | string[] | One or more test suite IDs to execute |
### On success
Extract the `runId` (execution ID) from the response. Inform the user:
> "Tests are running in `<doce-org-alias>`. I'll update you when results are ready."
Then proceed **immediately** to Step 2 (polling) with the `runId`.
### On error
See `references/error-handling.md`. If the org rejects execution (e.g. `environmentId: null`, or `classIdList is null or empty — no tests to execute`), read the actual error, explain the root cause and required fix in plain language, and finish cleanly. **Do not retry in a loop and do not fabricate a `runId` or results.**
---
## Step 2 — Poll until completion
**Confirmation required:** No — polling is automatic and read-only.
Poll the execution record by `runId` at the provider-appropriate interval. Full intervals, timeout behavior, and the poll query are in `references/polling-configuration.md`.
Summary of the loop (the `runId` is a `DevopsTestSuiteExecution` Id — poll that object, not `DevopsTestExecution`):
- Query `DevopsTestSuiteExecution` by `runId` each interval for `Status, Coverage, SuccessCount, FailureCount, QualityGateStatus`.
- `InProgress` → wait and poll again.
- `Passed` / `Failed` → surface `Coverage`, `SuccessCount`, `FailureCount`, and `QualityGateStatus` inline (no raw JSON). If `FailureCount > 0`, fetch the child `DevopsTestExecution` failure rows and hand off to **`dx-devops-test-failures-analyze`**.
- `Error` → the run itself errored (not test failures); surface `ResultDetails`/`Message` in plain language and offer retry or skip.
- **Timeout** → surface the `runId`, do NOT auto-retry, wait for user instruction.
---
## Retrigger mode (re-running a quality gate)
Use when a promotion was blocked by a gate failure and the coverage gap has since been addressed. **All preconditions, gate, and the retrigger API call are in `references/retrigger-mode.md`.** Key rule: do **not** retrigger unless the latest `Coverage` meets or exceeds the `DevopsQualityGateRule` threshold. After the retrigger returns a new `runId`, hand it to Step 2 (polling).
---
## Related skills
- **`dx-devops-test-failures-analyze`** — receives the failure payload on completion; can also create a fix work item.
- **`dx-devops-test-suite-assignments-configure`** — recommend which suites to run, or assign a suite to the stage if it isn't linked yet.
- **`dx-devops-test-pipeline-configure`** — configure a new quality gate or threshold (this skill only re-runs existing gates).

View File

@ -0,0 +1,31 @@
# Error Handling — Execution & Polling
Never expose raw API errors, stack traces, or JSON payloads to the user.
## Step 1 — Execute call
| Status | Message to user |
|---|---|
| 400 | "The test execution request was invalid. Check that the stage and suite IDs are correct." |
| 403 | "You don't have permission to run tests on this pipeline. Check your DevOps Testing API access." |
| 404 | "The pipeline or stage was not found. It may have been deleted." |
| 500 | "The DevOps Center org returned a server error. Try again in a few minutes." |
## Org-side execution rejections (read the real error, explain, finish — do NOT loop)
| Org error | Explanation to user |
|---|---|
| `environmentId: null` | "The environment connection isn't resolving for this stage. Re-authenticate or reconnect the stage's environment in DevOps Center, then try again." |
| `classIdList is null or empty — no tests to execute` | "The assigned suite(s) contain no test classes, so there's nothing to run. Add test classes to the suite (via dx-devops-test-suite-assignments-configure) and try again." |
In both cases: attempt the call once, explain the root cause and required fix, finish cleanly. Do NOT retry in a loop and do NOT fabricate a `runId` or results.
**Empty-org / no-data case:** If the stage has no assigned suites, report that clearly and do NOT call the execute endpoint or fabricate a suite/run.
## Step 2 — Polling
If no `DevopsTestExecution` record matches the runId, report it gracefully and do not fabricate result data. On timeout, surface the runId and wait for user instruction — never auto-retry.
## Do NOT use `sf apex run test`
That command is for the `platform-apex-test-run` skill, not DevOps Center test suites.

View File

@ -0,0 +1,78 @@
# Polling Configuration (Step 2)
**Confirmation required:** No — polling is automatic and read-only. No user confirmation gate is needed.
**What it does:** Polls the DevOps Center org for the status of an async test execution until it completes, times out, or fails.
## Prerequisites
You need an active `runId` (from Step 1, the execute call) and the confirmed `doce-org-alias`. If org context is not yet established, run Prerequisites 13 (`references/prerequisite-checks.md`).
## Inputs
| Input | Source |
|---|---|
| `runId` | Returned by the Step 1 execute call (or supplied by the user for an in-progress run) |
| `testType` | Derived from the suite's test provider (Apex, Code Analyzer, UI/Provar, Flow) |
| `doce-org-alias` | Established via prerequisites |
If the user is watching an already-running execution, resolve the `runId` by querying the most recent `DevopsTestExecution` for the relevant trigger, or use the runId the user provides.
## Polling intervals
| Test type | Poll interval | Max wait | Timeout action |
|---|---|---|---|
| Apex unit tests | 15 seconds | 5 minutes | Surface runId, offer retry |
| Code Analyzer | 10 seconds | 3 minutes | Surface runId, offer retry |
| UI tests (Provar) | 60 seconds | 20 minutes | Surface runId, mark as pending |
| Flow tests | 20 seconds | 8 minutes | Surface runId, offer retry |
## Object model — read the right object
The `runId` returned by the execute call is a **`DevopsTestSuiteExecution`** record Id (the suite-level run). Poll *that* object — it holds the status and the aggregate results. Per-test detail lives on child `DevopsTestExecution` records linked by `DevopsTestSuiteExecutionId`.
| Object | Role | Key fields |
|---|---|---|
| `DevopsTestSuiteExecution` (poll this) | Suite-level run = the `runId` | `Status`, `Coverage`, `SuccessCount`, `FailureCount`, `SuccessRate`, `FailureRate`, `QualityGateStatus`, `ExecutionEndTime`, `ResultDetails`, `ReportUrl` |
| `DevopsTestExecution` (per-test detail) | One row per test, linked via `DevopsTestSuiteExecutionId` | `Status`, `Message`, `Severity`, `ResultDetails`, `DevopsTestId` |
> Do NOT query `TestsRan`, `TestsPassed`, `TestsFailed`, or `CoveragePercentage` — those fields do not exist on either object and the query will fail with `INVALID_FIELD`. Use the field names in the table above.
## Poll query
Query the suite execution record by `runId` on each interval:
```bash
sf data query \
--query "SELECT Id, Status, Coverage, SuccessCount, FailureCount, QualityGateStatus FROM DevopsTestSuiteExecution WHERE Id = '<runId>' LIMIT 1" \
--target-org <doce-org-alias> \
--json
```
Check the `Status` picklist on each poll (valid values: `Passed`, `Failed`, `InProgress`, `Error`):
- `InProgress` → wait and poll again
- `Passed` → run completed successfully; surface results
- `Failed` → run completed with test failures; surface results, then fetch per-test detail (below) and hand off to analysis
- `Error` → the run itself errored (not a test failure); surface the `ResultDetails`/`Message` in plain language and offer retry or skip
## On timeout
Surface the `runId` to the user:
> "The test run is taking longer than expected. Your run ID is `<runId>`. You can check the status manually in DevOps Center, or I can keep waiting — what would you prefer?"
Do not automatically retry after timeout. Wait for user instruction.
## On completion
When `Status` is `Passed` or `Failed`, surface `Coverage`, `SuccessCount`, `FailureCount`, and `QualityGateStatus` from the `DevopsTestSuiteExecution` record inline (no raw JSON).
If `FailureCount > 0` (or `Status = Failed`), fetch the per-test failure detail from the child `DevopsTestExecution` records, then pass that payload to the **`dx-devops-test-failures-analyze`** skill:
```bash
sf data query \
--query "SELECT Id, Status, Message, Severity, ResultDetails, DevopsTestId FROM DevopsTestExecution WHERE DevopsTestSuiteExecutionId = '<runId>' AND Status = 'Failed'" \
--target-org <doce-org-alias> \
--json
```
**Empty / no-data case:** If no `DevopsTestSuiteExecution` record matches the runId, report that clearly and do NOT fabricate a runId, status, or result values.

View File

@ -0,0 +1,112 @@
# Prerequisite Checks — Shared DevOps Center Gate
Shared environment gate for every DevOps Center testing skill. Run these checks **before** any query or system call. On any failure, surface the plain-language message and stop until the user resolves it — never proceed to a write with an unverified environment.
> **API version:** All DevOps testing system calls target Salesforce API **v67.0** (minimum required).
**Important:** All DevOps Center data (pipelines, stages, test suites, executions) lives in the Salesforce org — NOT in the local repository. Never search the filesystem for pipeline configuration. Always query the org using `sf data query` or `sf api request rest`.
**Object model — use the STANDARD objects, never the `sf_devops__` managed package:** DevOps Center testing data lives in standard platform objects — `DevopsPipeline`, `DevopsPipelineStage`, `DevopsPipelineStageTrigger`, `DevopsTestSuite`, `DevopsTestSuiteStage`, `DevopsTestSuiteExecution`, `DevopsProject`, `WorkItem`. Do **NOT** query the legacy managed-package objects (`sf_devops__Pipeline__c`, `sf_devops__Pipeline_Stage__c`, etc.) and do **NOT** gate on a `PackageLicense` / namespace check for `sf_devops`. "DevOps Center installed" is determined **solely** by whether `DevopsPipeline` is queryable and returns records (Prerequisite 4) — never by the presence of the `sf_devops__` namespace. If a `sf_devops__*` object is missing, that is expected and is NOT evidence that DevOps Center is uninstalled.
## How skills use this
Run Prerequisites 14 in order. Prerequisite 5 (stage) is run **only** when the operation targets a specific pipeline stage (configuring a gate, running/retriggering a suite, mapping a suite). Carry forward the resolved `doce-org-alias`, `pipelineId`, and (when applicable) `stageId`.
Resolve the **DevOps Center org alias** without asking the user unless genuinely ambiguous:
1. If the user named an org alias in their message, use it.
2. Otherwise, use the default org (`sf org display --json`, no `--target-org`).
3. Only if the default org has no `DevopsPipeline` records (Prereq 4 fails), ask: "Which org alias is your DevOps Center org?"
---
## Prerequisite 1 — Salesforce org: active login
```bash
sf org list --json
```
Look for at least one entry in `result.nonScratchOrgs`, `result.scratchOrgs`, or `result.sandboxes` with `"connectedStatus": "Connected"`.
- **Pass:** at least one org is Connected
- **Fail:** no orgs listed, or all show a non-connected status
**On fail:** "No authenticated Salesforce org found. Run `sf org login web --alias <your-alias>` in your terminal, then come back."
---
## Prerequisite 2 — Agentforce DX plugin installed
```bash
sf plugins --json
```
Look for a plugin entry whose `name` contains `plugin-agent`, `agentforce`, or `einstein` (case-insensitive).
- **Pass:** plugin found
- **Fail:** no matching entry
**On fail:** "The Agentforce DX Plugin is not installed. Run `sf plugins install @salesforce/plugin-agent`, then restart the IDE and try again."
---
## Prerequisite 3 — DevOps Center org authenticated
```bash
sf org display --target-org <doce-org-alias> --json
```
Check that `"connectedStatus"` is `"Connected"`.
- **Pass:** Connected
- **Fail:** expired session or error
**On fail:** "Your DevOps Center org session has expired. Run `sf org login web --alias <doce-org-alias>` to re-authenticate."
---
## Prerequisite 4 — Pipeline identified
```bash
sf data query \
--query "SELECT Id, Name, CreatedDate FROM DevopsPipeline ORDER BY Name ASC" \
--target-org <doce-org-alias> \
--json
```
- **Pass (exactly one):** use it automatically — do NOT ask.
- **Pass (multiple):** if the user already named a pipeline, match by name. Otherwise display a numbered list and ask:
```text
Found <N> pipelines:
1. <Name>
2. <Name>
Which pipeline would you like to work with?
```
- **Fail (no records):** "No DevOps Center pipeline found. Create a project and pipeline in DevOps Center before using the DevOps Testing Skills."
- **Fail (unsupported object):** "DevOps Center does not appear to be installed on `<doce-org-alias>`. Check that you're pointing at the correct org."
---
## Prerequisite 5 — Pipeline stage identified (conditional)
Run **only** when the operation targets a specific stage (e.g. configuring a quality gate).
If the user's message already names a stage (e.g. "Integration", "Staging", "Production"), use that name directly — do NOT ask again. Look up its Id:
```bash
sf data query \
--query "SELECT Id, Name FROM DevopsPipelineStage WHERE DevopsPipelineId = '<pipelineId>' AND Name = '<stageName>'" \
--target-org <doce-org-alias> --json
```
Only if no stage is mentioned, fetch the full list and ask which one:
```bash
sf data query \
--query "SELECT Id, Name FROM DevopsPipelineStage WHERE DevopsPipelineId = '<pipelineId>' ORDER BY Name ASC" \
--target-org <doce-org-alias> --json
```
Then ask: "Which pipeline stage are we working with?" — do NOT ask for an org alias; stages are resolved by name from the pipeline.
- **Pass:** stage Id and Name confirmed
- **Deferred:** not required until the operation needs it

View File

@ -0,0 +1,51 @@
# Retrigger Mode — Re-running a Quality Gate
Use this mode when a promotion was blocked by a quality gate failure and the coverage gap has since been addressed.
## Extra preconditions — all must be true before proceeding
1. The `Coverage` field on the latest `DevopsTestSuiteExecution` meets or exceeds the threshold defined in the `DevopsQualityGateRule`.
2. The user has explicitly asked to retrigger the gate.
3. The same `pipelineId`, `stageId`, and `event` from the blocked promotion are known.
If coverage is still below threshold, do **not** retrigger. Instead respond:
> "Coverage is still at `<X>%`, below the `<threshold>%` gate. The gate cannot be retriggered until the threshold is met. Here are the remaining uncovered methods: `<list>`."
Do not retry. Explain what must be resolved first and stop.
## Inputs required for retrigger
| Input | Source |
|---|---|
| `pipelineId` | From the blocked promotion context |
| `stageId` | From the blocked promotion context |
| `event` | Same event type that originally blocked (`Pre-Promote` or `Post-Promote`) |
| `suiteIds` | Same suites that were originally run |
| `doce-org-alias` | Prerequisite 1 |
## Confirmation gate (retrigger)
Before executing the API call, present this confirmation prompt and wait for explicit user approval:
> "Coverage is confirmed at `<X>%`, which meets the `<threshold>%` gate. I'll retrigger the quality gate check for the `<stageName>` stage (`<event>`). Confirm?"
Only proceed after the user confirms. If the user declines, stop without making any API call.
## API call (retrigger)
Uses the same Connect API stage/execute endpoint:
```bash
sf api request rest "/services/data/v67.0/connect/devopstesting/pipeline/<pipelineId>/stage/execute" --method POST --body '{"stageId":"<stageId>","event":"<event>","testSuiteIds":["<suiteId1>"]}' --target-org <doce-org-alias>
```
After the call returns a `runId`, hand off to Step 2 (polling) with the new `runId` to monitor the execution result.
## Error handling (retrigger)
If the API returns an error indicating the gate cannot be retriggered, respond with:
> "The quality gate cannot be retriggered right now. Reason: `<plain-language summary>`. Here's what needs to be resolved first: `<list>`."
Never expose raw API error details to the user.

View File

@ -1,161 +0,0 @@
---
name: managing-suite-assignments
description: "Manages all forms of test suite assignment for DevOps Center pipeline stages via the Connect API testSuiteStages endpoint. Covers three modes: (A) attaching a single suite to a stage as a one-off add, (B) bulk-mapping multiple suites to a stage as a testing strategy with a mandatory impact-preview table before any changes, and (C) adding or removing individual test classes within a suite assignment with governance rules that exclude rejected tests and re-present the final list before committing. TRIGGER when: a suite is found unlinked from a pipeline stage and the user wants to assign it; the user wants to configure suite-to-stage mappings across a pipeline or assign multiple suites to stages as part of a testing strategy; the user wants to add or remove tests in a suite, sync reviewed tests into a suite, or promote tests to a suite. DO NOT TRIGGER when: authoring new test classes (use platform-apex-test-generate) or running tests directly (use platform-apex-test-run)."
metadata:
version: "1.0"
minApiVersion: "67.0"
---
# Managing Suite Assignments
## Prerequisites
Load `checking-devops-prerequisites` first — Prerequisites 14 AND Prerequisite 5 (stage). You need `doce-org-alias`, `pipelineId`, and `stageId` before proceeding in any mode.
| Variable | Description |
|---|---|
| `doce-org-alias` | Established in Prerequisite 1 |
| `pipelineId` | Identified in Prerequisite 4 (pipeline selection) |
| `stageId` | Identified in Prerequisite 5 (stage selection) |
| `event` | `Pre-Promote`, `Post-Promote`, or `Review` |
---
## Mode A — Assign a single suite to a stage
Use this mode when a relevant test suite already exists but is not yet linked to a pipeline stage and the user wants to add it as a single one-off assignment.
**Additional inputs required:**
| Variable | Description |
|---|---|
| `testSuiteId` | ID of the suite to assign |
| `testSuiteName` | Name of the suite (for display in confirmation) |
**Confirmation gate**
**Confirmation required before any API call is made.**
Present the following prompt to the user and wait for an affirmative response:
> "The suite `<testSuiteName>` is not currently assigned to the `<stageName>` stage (`<event>`). Would you like me to assign it now?"
Do not proceed until the user confirms.
**On success**
Report to the user:
> "Suite `<testSuiteName>` has been assigned to the `<stageName>` stage (`<event>`)."
---
## Mode B — Map multiple suites to a stage
Use this mode when configuring suite-to-stage mappings across a pipeline or assigning multiple suites to stages as part of a testing strategy.
**Additional inputs required:**
| Input | Description |
|---|---|
| `testSuiteOperations` | List of `{testSuiteId, action: "add"\|"remove"}` |
**MANDATORY IMPACT PREVIEW — Required Before Any Changes**
**Do not call the API until the user has confirmed the preview below.**
Present the full mapping summary and wait for explicit confirmation:
> "Here's the suite mapping I'll apply:
>
> | Suite | Stage | Event | Action |
> |---|---|---|---|
> | `<suiteName>` | `<stageName>` | `<event>` | Add |
> | `<suiteName2>` | `<stageName>` | `<event>` | Remove |
>
> Confirm to apply all changes?"
Only proceed after the user explicitly confirms.
**On success**
> "Suite mapping applied. `<N>` suite(s) updated for the `<stageName>` stage."
---
## Mode C — Add/remove test classes in a suite
Use this mode when the user wants to add or remove individual test classes within an existing suite assignment, sync reviewed tests into a suite, or promote tests to a suite.
**Additional inputs required:**
| Input | Source |
|---|---|
| `testSuiteOperations` | List of `{testSuiteId, action: "add"\|"remove"}` |
**Governance rules**
- **Never call this without explicit approval.** AI-reviewed or modified tests must be re-presented to the user before this call is made.
- Rejected tests must be EXCLUDED from the payload — do not include them even if they were previously in the suite.
- If tests were modified during review, re-present the final list of tests before requesting confirmation.
**Confirmation gate**
**REQUIRED — do not skip.** Show the user the full list of changes before calling:
> "I'm about to sync the following changes to the test suite:
> - **Add:** `<testSuiteName1>`, `<testSuiteName2>`
> - **Remove:** `<testSuiteName3>`
> - Stage: `<stageName>` | Event: `<event>`
>
> Confirm?"
Only proceed after receiving explicit confirmation.
**On success**
Confirm to the user:
> "Test suite updated successfully for the `<stageName>` stage."
---
## The system call
All three modes use the same endpoint. Substitute all `<placeholder>` values before executing.
```bash
sf api request rest "/services/data/v67.0/connect/devopstesting/pipeline/<pipelineId>/testSuiteStages" --method POST --body '{"pipelineStageId":"<stageId>","event":"<event>","assignments":[{"testSuiteId":"<id>","action":"add|remove"}]}' --target-org <doce-org-alias>
```
Full payload schema:
```json
{
"pipelineStageId": "<stageId>",
"event": "<event>",
"assignments": [
{"testSuiteId": "<suiteId1>", "action": "add"},
{"testSuiteId": "<suiteId2>", "action": "remove"}
]
}
```
**Error handling**
Never expose raw API error messages to the user. Map response status codes to the following user-facing messages:
| Status | User-facing message |
|---|---|
| 400 | "The request was invalid. Check that all suite and stage IDs are correct and the event type is valid." |
| 403 | "You don't have permission to modify suite assignments on this pipeline." |
| 404 | "The pipeline or stage was not found." |
| 500 | "A server error occurred. Try again in a few minutes." |
---
## Related skills
- **`syncing-test-providers`** — use when the suite you want to assign doesn't appear yet; re-syncing the provider pulls in newly added suites.
- **`recommending-devops-tests`** — use when a suite has not yet been identified and you need a recommendation for which suite to assign.
- **`configuring-quality-gate`** — use to configure a quality gate on the stage after mapping suites.
- **`analyzing-test-failures`** — use for failure analysis and suggested improvements to the tests within a suite.

View File

@ -1,72 +0,0 @@
---
name: polling-test-results
description: "Polls a DevOps Center async test execution by runId until it completes, fails, or times out — using read-only SOQL on the execution record at provider-specific intervals (Apex 15s/5m, Code Analyzer 10s/3m, Provar UI 60s/20m, Flow 20s/8m) — then surfaces results. Use this skill when a test suite run is in progress and the user is waiting on results, or immediately after running a suite. TRIGGER when: a test suite run is in progress and the user is waiting on results, or immediately after running a suite and a runId is available. DO NOT TRIGGER when: there is no active runId."
metadata:
version: "1.0"
minApiVersion: "67.0"
---
# polling-test-results
**Confirmation required:** No — polling is automatic and read-only. No user confirmation gate is needed.
**What it does:** Polls the DevOps Center org for the status of an async test execution until it completes, times out, or fails.
---
## Prerequisites
You need an active `runId` (returned by the `running-devops-test-suite` skill) and the confirmed `doce-org-alias`. If org context is not yet established, load `checking-devops-prerequisites` first (Prerequisites 13).
---
## Inputs required
| Input | Source |
|---|---|
| `runId` | Returned by the `running-devops-test-suite` skill |
| `testType` | Derived from the suite's test provider (Apex, Code Analyzer, UI/Provar, Flow) |
| `doce-org-alias` | Established via `checking-devops-prerequisites` |
## Polling configuration
| Test type | Poll interval | Max wait | Timeout action |
|---|---|---|---|
| Apex unit tests | 15 seconds | 5 minutes | Surface runId, offer retry |
| Code Analyzer | 10 seconds | 3 minutes | Surface runId, offer retry |
| UI tests (Provar) | 60 seconds | 20 minutes | Surface runId, mark as pending |
| Flow tests | 20 seconds | 8 minutes | Surface runId, offer retry |
## Poll query
Query the execution record by `runId` on each interval:
```bash
sf data query \
--query "SELECT Id, Status, TestsRan, TestsPassed, TestsFailed, CoveragePercentage FROM DevopsTestExecution WHERE Id = '<runId>' LIMIT 1" \
--target-org <doce-org-alias> \
--json
```
Check the `Status` field on each poll:
- `Queued` / `Running` → wait and poll again
- `Completed` → proceed to result analysis
- `Failed` → surface error and offer retry or skip
## On timeout
Surface the `runId` to the user:
> "The test run is taking longer than expected. Your run ID is `<runId>`. You can check the status manually in DevOps Center, or I can keep waiting — what would you prefer?"
Do not automatically retry after timeout. Wait for user instruction.
## On completion
Pass the full result payload to the `analyzing-test-failures` skill for reasoning. Surface `Coverage`, `SuccessCount`, `FailureCount`, and `QualityGateStatus` inline. Do not surface raw JSON to the user.
---
## Related skills
- Runs are started by `running-devops-test-suite` (including its retrigger mode)
- Failure analysis is handled by `analyzing-test-failures`

View File

@ -1,144 +0,0 @@
---
name: running-devops-test-suite
description: "Triggers async execution of one or more DevOps Center test suites on a pipeline stage (Pre-Promote, Post-Promote, or Review event) via the Connect API, after an explicit user confirmation gate, then hands off to result polling via the `polling-test-results` skill. Also re-runs (retriggers) a quality gate after fixes — but only once validation confirms the coverage threshold is now met. TRIGGER when: the user wants to run, kick off, or launch test suites on a pipeline stage; execute tests before or after a promotion; trigger a Pre-Promote, Post-Promote, or Review-event run; re-run a quality gate after fixing failures; retry a failed gate once coverage is met; or unblock a blocked promotion after adding tests. DO NOT TRIGGER when: running sf apex run test directly (use platform-apex-test-run); or configuring a NEW gate or threshold (use configuring-quality-gate)."
metadata:
version: "1.0"
minApiVersion: "67.0"
---
# Running a DevOps Center Test Suite
## Prerequisites
Load and follow `checking-devops-prerequisites` first — run Prerequisites 14 AND Prerequisite 5 (pipeline stage), since this skill operates on a specific stage. You need the confirmed `doce-org-alias`, `pipelineId`, and `stageId` before proceeding.
## Inputs required before calling this skill
| Input | How to obtain |
|---|---|
| `pipelineId` | From Prerequisite 4 (pipeline selection) |
| `stageId` | From Prerequisite 5 (pipeline stage confirmation) |
| `event` | Confirm with user: `Pre-Promote` or `Post-Promote` (or `Review` if the context is a review environment) |
| `testSuiteIds` | Confirmed suite IDs from the suite selection or recommendation step |
| `doce-org-alias` | Established in Prerequisite 1 |
## Confirmation gate
**This call mutates org state — do not proceed without explicit user confirmation.**
Before calling the API, show the user:
> "I'm about to run tests with the following configuration:
> - Pipeline: `<pipelineName>`
> - Stage: `<stageName>`
> - Event: `<event>`
> - Suite(s): `<suiteName(s)>`
> - Org: `<doce-org-alias>`
>
> Shall I proceed?"
Do not make the API call until the user confirms.
## API call
```bash
sf api request rest \
"/services/data/v67.0/connect/devopstesting/pipeline/<pipelineId>/stage/execute" \
--method POST \
--body '{
"stageId": "<stageId>",
"event": "<event>",
"testSuiteIds": ["<suiteId1>", "<suiteId2>"]
}' \
--target-org <doce-org-alias>
```
### Body schema
| Field | Type | Description |
|---|---|---|
| `stageId` | string | The ID of the pipeline stage to execute tests on |
| `event` | string | `Pre-Promote`, `Post-Promote`, or `Review` |
| `testSuiteIds` | string[] | One or more test suite IDs to execute |
## On success
Extract the `runId` (or execution ID) from the response. Inform the user:
> "Tests are running in `<doce-org-alias>`. I'll update you when results are ready."
Immediately hand off the `runId` to the `polling-test-results` skill to begin the polling loop.
## On error
| Status | Message to user |
|---|---|
| 400 | "The test execution request was invalid. Check that the stage and suite IDs are correct." |
| 403 | "You don't have permission to run tests on this pipeline. Check your DevOps Testing API access." |
| 404 | "The pipeline or stage was not found. It may have been deleted." |
| 500 | "The DevOps Center org returned a server error. Try again in a few minutes." |
Never expose raw API errors to the user.
---
## Retrigger mode (re-running a quality gate)
Use this mode when a promotion was blocked by a quality gate failure and the coverage gap has since been addressed.
### Extra preconditions — all must be true before proceeding
1. The `Coverage` field on the latest `DevopsTestSuiteExecution` meets or exceeds the threshold defined in the `DevopsQualityGateRule`
2. The user has explicitly asked to retrigger the gate
3. The same `pipelineId`, `stageId`, and `event` from the blocked promotion are known
If coverage is still below threshold, do **not** retrigger. Instead, respond:
> "Coverage is still at `<X>%`, below the `<threshold>%` gate. The gate cannot be retriggered until the threshold is met. Here are the remaining uncovered methods: `<list>`."
Do not retry. Explain what must be resolved first and stop.
### Inputs required for retrigger
| Input | Source |
|---|---|
| `pipelineId` | From the blocked promotion context |
| `stageId` | From the blocked promotion context |
| `event` | Same event type that originally blocked (`Pre-Promote` or `Post-Promote`) |
| `suiteIds` | Same suites that were originally run |
| `doce-org-alias` | Established in Prerequisite 1 |
### Confirmation gate (retrigger)
Before executing the API call, present this confirmation prompt and wait for explicit user approval:
> "Coverage is confirmed at `<X>%`, which meets the `<threshold>%` gate. I'll retrigger the quality gate check for the `<stageName>` stage (`<event>`). Confirm?"
Only proceed after the user confirms. If the user declines, stop without making any API call.
### API call (retrigger)
Uses the same Connect API stage/execute endpoint:
```bash
sf api request rest "/services/data/v67.0/connect/devopstesting/pipeline/<pipelineId>/stage/execute" --method POST --body '{"stageId":"<stageId>","event":"<event>","testSuiteIds":["<suiteId1>"]}' --target-org <doce-org-alias>
```
After the call returns a `runId`, hand off to the `polling-test-results` skill with the new `runId` to monitor the execution result.
### Error handling (retrigger)
If the API returns an error indicating the gate cannot be retriggered, respond with:
> "The quality gate cannot be retriggered right now. Reason: `<plain-language summary>`. Here's what needs to be resolved first: `<list>`."
Never expose raw API error details to the user.
---
## Related skills
- **`polling-test-results`** — poll for async run results after receiving the `runId`
- **`recommending-devops-tests`** — recommend which suites to run first before triggering execution
- **`managing-suite-assignments`** — assign or map a suite to a pipeline stage if it isn't linked yet
- **`configuring-quality-gate`** — configure a new gate or threshold

View File

@ -1,108 +0,0 @@
---
name: syncing-test-providers
description: "Re-syncs a configured DevOps Center test provider on a pipeline to pick up new test suites, via the Connect API sync endpoint, after explicit user confirmation. Takes a pipelineId and one or more testProviderIds and triggers an asynchronous re-sync so newly added suites become available for assignment. Use this skill when a test provider (e.g. Apex Unit Tests, Code Analyzer, Flow Tests, Provar) has had suites added since it was last configured and the user wants those suites to show up in DevOps Center. TRIGGER when: the user wants to re-sync a test provider, pull in new suites from a provider, refresh a provider's suite list, or says assigned suites are missing/out of date for a configured provider. DO NOT TRIGGER when: configuring a provider for the first time (that creates a new DevopsPipelineTestProvider configuration), or assigning/mapping existing suites to a stage (use managing-suite-assignments)."
metadata:
version: "1.0"
minApiVersion: "67.0"
---
# Syncing Test Providers
Re-syncs a configured test provider on a DevOps Center pipeline so that suites added to the provider since it was last configured become available for assignment to stages.
**Confirmation required:** Yes — explicit confirmation before the sync is triggered.
## Prerequisites
Load `checking-devops-prerequisites` first — Prerequisites 14 (org login, Agentforce DX plugin, DevOps Center org auth, pipeline identified). Prerequisite 5 (stage) is **not** required: providers are synced at the pipeline level, not the stage level.
| Variable | Source |
|---|---|
| `doce-org-alias` | Established in Prerequisite 1 |
| `pipelineId` | Identified in Prerequisite 4 (pipeline selection) |
| `testProviderId` | Resolved by fetching the pipeline's test providers (below) |
---
## Step 1 — Fetch test providers to resolve the provider ID
Get all test providers configured on the pipeline so you can resolve the `testProviderId` and confirm the provider name with the user:
```bash
sf api request rest \
"/services/data/v67.0/connect/devopstesting/pipeline/<pipelineId>/testProviders?status=all" \
--target-org <doce-org-alias>
```
Each provider entry includes `testProviderId`, `testProviderName`, and a status (Configured vs. Available). Present a short summary grouped by status:
```text
Test providers for <pipelineName>:
✓ Configured:
- Code Analyzer (63 suites)
- Apex Unit Tests (5 suites)
Available (not yet configured):
- Flow Tests
```
- **Only a Configured provider can be synced.** If the user names an *Available* (not-yet-configured) provider, explain it must be configured first — this skill does not configure providers.
- If the pipeline has no configured providers, report that and stop — do NOT fabricate a provider or ID.
## Step 2 — Confirmation gate
**Required — do not call the API before the user confirms.**
> "I'll re-sync `<testProviderName>` on the `<pipelineName>` pipeline to pick up any new suites. Confirm?"
Do not proceed until the user gives an affirmative response.
## Step 3 — Trigger the sync
On confirmation, call the sync endpoint with the provider ID(s) and pipeline ID:
```bash
sf api request rest \
"/services/data/v67.0/connect/devops/sync" \
--method POST \
--body '{
"testProviderIds": ["<testProviderId>"],
"pipelineId": "<pipelineId>"
}' \
--target-org <doce-org-alias>
```
`testProviderIds` is a list — multiple configured providers can be synced in one call.
## On success
> "Provider `<testProviderName>` sync started. The operation is running asynchronously — new suites will be available shortly."
The sync runs asynchronously; newly synced suites can then be assigned to stages with `managing-suite-assignments`.
---
## Critical gotcha
**Do NOT use** `POST /connect/devops/pipeline/<pipelineId>/testProvider` to sync — that endpoint **creates a new provider configuration** and will result in duplicate `DevopsPipelineTestProvider` records. Sync only via `POST /connect/devops/sync`.
## Error Handling
Never expose raw API error messages, stack traces, or JSON payloads to the user. Map response status codes to plain-language messages:
| Status | User-facing message |
|---|---|
| 400 | "The sync request was invalid. Check that the provider ID and pipeline ID are correct." |
| 403 | "You don't have permission to sync test providers on this pipeline." |
| 404 | "The pipeline or test provider was not found." |
| 500 | "A server error occurred. Try again in a few minutes." |
---
## Related skills
- **`checking-devops-prerequisites`** — loaded first to establish org and pipeline context.
- **`configuring-test-provider`** — use to configure an available provider for the first time; this skill only re-syncs already-configured providers.
- **`managing-suite-assignments`** — after a sync surfaces new suites, use this to assign or map them to a pipeline stage.
- **`recommending-devops-tests`** — to recommend which of the newly synced suites to run.