@salesforce/afv-skills 1.45.0 → 1.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/package.json +1 -1
  2. package/skills/agentforce-observe/SKILL.md +32 -4
  3. package/skills/agentforce-observe/references/ahm-alerts.md +719 -0
  4. package/skills/automation-flow-generate/SKILL.md +11 -5
  5. package/skills/consumer-goods-promotion-bo-api-deploy/SKILL.md +275 -0
  6. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/README.md +32 -0
  7. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/SetCommentValue.cls +75 -0
  8. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/SetCommentValue.cls-meta.xml +5 -0
  9. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/interview-answers.json +13 -0
  10. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/copy.json +10 -0
  11. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/create.json +20 -0
  12. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/update.json +16 -0
  13. package/skills/consumer-goods-promotion-bo-api-deploy/references/conventions-and-payload-rules.md +273 -0
  14. package/skills/consumer-goods-promotion-bo-api-deploy/references/generate-and-wire.md +236 -0
  15. package/skills/consumer-goods-promotion-bo-api-deploy/references/reference-example-set-comment-value.md +132 -0
  16. package/skills/consumer-goods-promotion-bo-api-deploy/references/smoke-and-verify.md +211 -0
  17. package/skills/dx-code-analyzer-configure/scripts/validate-config.sh +14 -10
  18. package/skills/dx-code-analyzer-run/scripts/apply-fixes.js +45 -4
  19. package/skills/dx-code-analyzer-run/scripts/describe-rule.js +52 -32
  20. package/skills/dx-devops-project-manage/SKILL.md +197 -0
  21. package/skills/dx-devops-project-manage/examples/common-workflows.md +197 -0
  22. package/skills/dx-devops-project-manage/references/cli-commands.md +295 -0
  23. package/skills/dx-devops-project-manage/scripts/create-project.sh +48 -0
  24. package/skills/dx-devops-project-manage/scripts/list-projects.sh +51 -0
  25. package/skills/dx-devops-project-manage/scripts/update-project.sh +96 -0
  26. package/skills/education-cloud-academic-calendar-generate/SKILL.md +225 -0
  27. package/skills/education-cloud-academic-calendar-generate/examples/quarter-calendar.json +47 -0
  28. package/skills/education-cloud-academic-calendar-generate/examples/sample-output.md +57 -0
  29. package/skills/education-cloud-academic-calendar-generate/examples/semester-calendar.json +54 -0
  30. package/skills/education-cloud-academic-calendar-generate/references/calendar-systems.md +127 -0
  31. package/skills/education-cloud-academic-calendar-generate/references/date-validation.md +222 -0
  32. package/skills/education-cloud-academic-calendar-generate/references/foundation_prerequisites.md +40 -0
  33. package/skills/education-cloud-academic-calendar-generate/scripts/validate_calendar_dates.py +143 -0
  34. package/skills/education-cloud-course-catalog-migrate/SKILL.md +321 -0
  35. package/skills/education-cloud-course-catalog-migrate/references/gotchas-detail.md +16 -0
  36. package/skills/education-cloud-course-catalog-migrate/references/gotchas.md +16 -0
  37. package/skills/education-cloud-course-catalog-migrate/references/large-catalog-handling.md +42 -0
  38. package/skills/education-cloud-course-catalog-migrate/scripts/batch_courses.py +36 -0
  39. package/skills/education-cloud-course-catalog-migrate/scripts/detect_linked_courses.py +51 -0
  40. package/skills/education-cloud-course-catalog-migrate/scripts/detect_modality_variants.py +48 -0
  41. package/skills/education-cloud-course-catalog-migrate/scripts/resolve_api_version.py +43 -0
  42. package/skills/education-cloud-course-catalog-migrate/scripts/split_course_code.py +39 -0
  43. package/skills/education-cloud-course-catalog-migrate/scripts/validate_completeness.py +54 -0
  44. package/skills/education-cloud-multi-campus-configure/references/foundation_prerequisites.md +3 -5
  45. package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +177 -0
  46. package/skills/education-cloud-student-recruitment-agent-configure/references/agent-and-subagents.md +151 -0
  47. package/skills/education-cloud-student-recruitment-agent-configure/references/customer-narration.md +34 -0
  48. package/skills/education-cloud-student-recruitment-agent-configure/references/execution-model.md +54 -0
  49. package/skills/education-cloud-student-recruitment-agent-configure/references/flows.md +82 -0
  50. package/skills/education-cloud-student-recruitment-agent-configure/references/grounding.md +199 -0
  51. package/skills/education-cloud-student-recruitment-agent-configure/references/permissions.md +183 -0
  52. package/skills/education-cloud-student-recruitment-agent-configure/references/platform-enablement.md +82 -0
  53. package/skills/education-cloud-student-recruitment-agent-configure/references/prerequisites.md +158 -0
  54. package/skills/education-cloud-student-recruitment-agent-configure/references/routing.md +141 -0
  55. package/skills/experience-cms-brand-apply/SKILL.md +5 -5
  56. package/skills/experience-cms-brand-create/SKILL.md +2 -2
  57. package/skills/experience-cms-content-generate/SKILL.md +1 -0
  58. package/skills/experience-cms-content-render/SKILL.md +173 -0
  59. package/skills/experience-cms-content-render/assets/angular/DetailPage.component.ts +25 -0
  60. package/skills/experience-cms-content-render/assets/angular/MediaRenderer.component.ts +133 -0
  61. package/skills/experience-cms-content-render/assets/angular/TypeList.component.ts +38 -0
  62. package/skills/experience-cms-content-render/assets/angular/TypeRenderer.component.ts +90 -0
  63. package/skills/experience-cms-content-render/assets/angular/cms-content.component.ts +248 -0
  64. package/skills/experience-cms-content-render/assets/angular/cms-item.service.ts +100 -0
  65. package/skills/experience-cms-content-render/assets/react/DetailPage.tsx +20 -0
  66. package/skills/experience-cms-content-render/assets/react/MediaRenderer.tsx +129 -0
  67. package/skills/experience-cms-content-render/assets/react/TypeList.tsx +40 -0
  68. package/skills/experience-cms-content-render/assets/react/TypeRenderer.tsx +64 -0
  69. package/skills/experience-cms-content-render/assets/react/heuristicRenderer.tsx +310 -0
  70. package/skills/experience-cms-content-render/assets/react/useCmsItem.ts +129 -0
  71. package/skills/experience-cms-content-render/assets/shared/cmsContentType.ts +49 -0
  72. package/skills/experience-cms-content-render/assets/shared/cmsCore.types.ts +96 -0
  73. package/skills/experience-cms-content-render/assets/shared/externalRefs.ts +55 -0
  74. package/skills/experience-cms-content-render/references/bulk-loading.md +60 -0
  75. package/skills/experience-cms-content-render/references/codegen-guardrails.md +111 -0
  76. package/skills/experience-cms-content-render/references/detail-pages.md +87 -0
  77. package/skills/experience-cms-content-render/references/embed-recipes.md +127 -0
  78. package/skills/experience-cms-content-render/references/failure-modes.md +96 -0
  79. package/skills/experience-cms-content-render/references/heuristic-render-rules.md +131 -0
  80. package/skills/experience-cms-content-render/references/init-scaffold.md +122 -0
  81. package/skills/experience-cms-content-render/references/interaction-model.md +173 -0
  82. package/skills/experience-cms-content-render/references/package-api.md +106 -0
  83. package/skills/experience-cms-content-render/references/schema-sync.md +114 -0
  84. package/skills/experience-cms-content-render/references/styling-scopes.md +65 -0
  85. package/skills/experience-cms-content-render/references/verify.md +49 -0
  86. package/skills/experience-cms-content-type-generate/SKILL.md +2 -2
  87. package/skills/experience-content-media-stock-image-search/SKILL.md +5 -4
  88. package/skills/experience-search-coordinate/SKILL.md +198 -0
  89. package/skills/experience-search-coordinate/assets/search-payload-template.json +25 -0
  90. package/skills/experience-search-coordinate/references/content-route.md +313 -0
  91. package/skills/experience-search-coordinate/references/content-type-discovery.md +57 -0
  92. package/skills/experience-search-coordinate/references/media-route.md +172 -0
  93. package/skills/experience-search-coordinate/references/scope-resolution.md +14 -0
  94. package/skills/experience-ui-bundle-localize/SKILL.md +1 -1
  95. package/skills/experience-ui-bundle-localize/references/i18n-setup.md +5 -3
  96. package/skills/experience-ui-bundle-project-generate/SKILL.md +18 -14
  97. package/skills/experience-ui-bundle-project-generate/references/angular-project-generate.md +22 -0
  98. package/skills/experience-ui-bundle-project-generate/references/react-project-generate.md +20 -0
  99. package/skills/experience-ui-bundle-salesforce-data-access/SKILL.md +58 -54
  100. package/skills/experience-ui-bundle-salesforce-data-access/references/caching.md +6 -0
  101. package/skills/experience-ui-bundle-salesforce-data-access/references/graphiti-cli.md +2 -2
  102. package/skills/experience-ui-bundle-salesforce-data-access/references/migration.md +6 -0
  103. package/skills/experience-ui-bundle-salesforce-data-access/references/rest-and-integration.md +2 -1
  104. package/skills/experience-ui-bundle-salesforce-data-access/references/sdk-api.md +6 -0
  105. package/skills/experience-ui-bundle-site-generate/SKILL.md +59 -8
  106. package/skills/experience-ui-bundle-site-generate/references/configure-metadata-digital-experience.md +8 -3
  107. package/skills/experience-ui-bundle-site-generate/references/configure-metadata-language-settings.md +120 -0
  108. package/skills/life-sciences-fieldsalesrep-coordinate/SKILL.md +336 -0
  109. package/skills/life-sciences-fieldsalesrep-coordinate/references/orchestration-flow.md +143 -0
  110. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-application-flexipage-mapping.md +127 -0
  111. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-deploy-commands.md +116 -0
  112. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-lifesci-metadata-deploy.md +111 -0
  113. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-overview.md +312 -0
  114. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-profile-layout-assignments.md +171 -0
  115. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-state-tracking.md +64 -0
  116. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-trigger-handlers.md +122 -0
  117. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-4-user-provisioning-overview.md +335 -0
  118. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-4-user-provisioning-user-provisioning-details.md +140 -0
  119. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-execution-state-and-recovery.md +196 -0
  120. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-metadata-cache-generation.md +155 -0
  121. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-overview.md +307 -0
  122. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-visit-creation-data.md +211 -0
  123. package/skills/life-sciences-fieldsalesrep-coordinate/references/state-machine-and-changes.md +108 -0
  124. package/skills/life-sciences-kam-coordinate/SKILL.md +241 -0
  125. package/skills/life-sciences-kam-coordinate/references/orchestration-flow.md +152 -0
  126. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-application-flexipage-mapping.md +79 -0
  127. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-deploy-commands.md +131 -0
  128. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-kam-config-records.md +85 -0
  129. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-lifesci-metadata-deploy.md +112 -0
  130. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-overview.md +202 -0
  131. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-profile-layout-assignments.md +67 -0
  132. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-state-tracking.md +65 -0
  133. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-trigger-handlers.md +123 -0
  134. package/skills/life-sciences-kam-coordinate/references/stage-4-participant-role-and-sprint.md +89 -0
  135. package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md +337 -0
  136. package/skills/life-sciences-kam-coordinate/references/stage-5-data-creation-data.md +248 -0
  137. package/skills/life-sciences-kam-coordinate/references/stage-6-ipad-validation-script.md +35 -0
  138. package/skills/life-sciences-kam-coordinate/references/stage-6-metadata-cache-generation.md +155 -0
  139. package/skills/life-sciences-kam-coordinate/references/stage-6-user-provisioning-details.md +146 -0
  140. package/skills/life-sciences-kam-coordinate/references/stage-6-user-provisioning-overview.md +89 -0
  141. package/skills/life-sciences-kam-coordinate/references/state-machine-and-changes.md +114 -0
  142. package/skills/life-sciences-prerequisites-validate/SKILL.md +138 -0
  143. package/skills/life-sciences-prerequisites-validate/references/checks-org-settings.md +190 -0
  144. package/skills/life-sciences-prerequisites-validate/references/checks-user-and-package.md +211 -0
  145. package/skills/life-sciences-territory-configure/SKILL.md +217 -0
  146. package/skills/life-sciences-territory-configure/references/territory-metadata.md +262 -0
  147. package/skills/platform-apex-logs-debug/SKILL.md +7 -7
  148. package/skills/platform-custom-application-generate/SKILL.md +4 -4
  149. package/skills/platform-custom-object-generate/SKILL.md +7 -7
  150. package/skills/platform-custom-tab-generate/SKILL.md +1 -1
  151. package/skills/platform-dsar-policy-manage/SKILL.md +272 -0
  152. package/skills/platform-dsar-policy-manage/references/configure.md +106 -0
  153. package/skills/platform-dsar-policy-manage/references/export-and-history.md +123 -0
  154. package/skills/platform-dsar-policy-manage/references/gap-analysis-guide.md +150 -0
  155. package/skills/platform-dsar-policy-manage/references/gap-scan.md +129 -0
  156. package/skills/platform-dsar-policy-manage/references/headless-sor.md +59 -0
  157. package/skills/platform-dsar-policy-manage/references/report-format.md +59 -0
  158. package/skills/platform-dsar-policy-manage/scripts/tests/__init__.py +0 -0
  159. package/skills/platform-dsar-policy-manage/scripts/tests/test_validate_policy_tree.py +76 -0
  160. package/skills/platform-dsar-policy-manage/scripts/validate-policy-tree.py +130 -0
  161. package/skills/platform-flexipage-generate/SKILL.md +4 -0
  162. package/skills/platform-list-view-generate/SKILL.md +1 -0
  163. package/skills/platform-salesforce-connect-adapter-generate/SKILL.md +359 -0
  164. package/skills/platform-salesforce-connect-adapter-generate/references/official-examples.md +69 -0
  165. package/skills/platform-salesforce-connect-adapter-generate/references/scenarios.md +187 -0
  166. package/skills/platform-soql-query/SKILL.md +8 -8
  167. package/skills/platform-value-set-generate/SKILL.md +2 -2
  168. package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +20 -27
  169. package/skills/service-native-voice-recording-transcription-configure/SKILL.md +47 -27
  170. package/skills/service-native-voice-recording-transcription-configure/references/thunderbird-voice-settings.md +13 -9
  171. package/skills/service-native-voice-recording-transcription-configure/scripts/enable-recording-transcription.sh +104 -45
@@ -0,0 +1,197 @@
1
+ # Common Project Management Workflows
2
+
3
+ Real-world examples of typical project operations in DevOps Center autonomous release scenarios.
4
+
5
+ ---
6
+
7
+ ## Workflow 1: List All Projects
8
+
9
+ **User request:** "Show me all DevOps Center projects in this org"
10
+
11
+ **Steps:**
12
+
13
+ 1. **Verify authentication**:
14
+ ```bash
15
+ sf org display --json
16
+ ```
17
+
18
+ 2. **List projects**:
19
+ ```bash
20
+ sf devops project list --target-org my-devops-org --json
21
+ ```
22
+
23
+ 3. **Present in a readable format**:
24
+ ```bash
25
+ sf devops project list --target-org my-devops-org --json | \
26
+ jq -r '.result.projects[] | "\(.Id): \(.Name) — \(.Description // "(no description)")"'
27
+ ```
28
+ Output:
29
+ ```text
30
+ 1Qg000000000001: Project Alpha — Core platform release pipeline
31
+ 1Qg000000000002: Project Beta — (no description)
32
+ ```
33
+
34
+ ---
35
+
36
+ ## Workflow 2: Create a New Project (Entry Point for a Release)
37
+
38
+ **User request:** "Set up a new DevOps Center project called 'Release Q3' for our Q3 features"
39
+
40
+ **Steps:**
41
+
42
+ 1. **Idempotent check** — confirm it doesn't already exist:
43
+ ```bash
44
+ NAME="Release Q3"
45
+ EXISTING_ID=$(sf devops project list --target-org my-devops-org --json | \
46
+ jq -r ".result.projects[] | select(.Name == \"$NAME\") | .Id" | head -n1)
47
+ ```
48
+
49
+ 2. **Create only if not found**:
50
+ ```bash
51
+ if [ -n "$EXISTING_ID" ]; then
52
+ echo "Project already exists: $EXISTING_ID"
53
+ else
54
+ # Create, then read the ID back from the authoritative list envelope
55
+ sf devops project create \
56
+ --target-org my-devops-org \
57
+ --name "$NAME" \
58
+ --description "Q3 feature release pipeline" \
59
+ --json >/dev/null
60
+ NEW_ID=$(sf devops project list --target-org my-devops-org --json | \
61
+ jq -r ".result.projects[] | select(.Name == \"$NAME\") | .Id" | head -n1)
62
+ echo "Created project: $NEW_ID"
63
+ fi
64
+ ```
65
+
66
+ > In practice, use `scripts/create-project.sh "$NAME" "Q3 feature release pipeline"` — it performs this idempotent create-then-verify and prints `EXISTING <id>` or `CREATED <id>`.
67
+
68
+ 3. **Hand off the project ID** to `dx-devops-work-item-manage` or `dx-devops-pipeline-manage` for the next steps.
69
+
70
+ ---
71
+
72
+ ## Workflow 3: Resolve a Project Name to Its ID
73
+
74
+ **User request:** "What's the project ID for Project Alpha?"
75
+
76
+ **Steps:**
77
+
78
+ 1. **Filter the list by name**:
79
+ ```bash
80
+ sf devops project list --target-org my-devops-org --json | \
81
+ jq -r '.result.projects[] | select(.Name == "Project Alpha") | .Id'
82
+ ```
83
+ Output: `1Qg000000000001`
84
+
85
+ 2. **Return the ID** so downstream skills (work items, pipelines) can use it.
86
+
87
+ ---
88
+
89
+ ## Workflow 4: Rename a Project
90
+
91
+ **User request:** "Rename 'Project Alpha' to 'Platform Core'"
92
+
93
+ Resolve the name to an ID, update it, then verify:
94
+
95
+ ```bash
96
+ PROJECT_ID=$(sf devops project list --target-org my-devops-org --json | \
97
+ jq -r '.result.projects[] | select(.Name == "Project Alpha") | .Id')
98
+
99
+ sf devops project update \
100
+ --target-org my-devops-org \
101
+ --project-id "$PROJECT_ID" \
102
+ --name "Platform Core" \
103
+ --json
104
+
105
+ sf devops project list --target-org my-devops-org --json | \
106
+ jq -r ".result.projects[] | select(.Id == \"$PROJECT_ID\") | .Name" # -> Platform Core
107
+ ```
108
+
109
+ ---
110
+
111
+ ## Workflow 5: Update Project Description
112
+
113
+ **User request:** "Update the description for project 1Qg000000000001 to note it now covers services too"
114
+
115
+ ```bash
116
+ sf devops project update \
117
+ --target-org my-devops-org \
118
+ --project-id 1Qg000000000001 \
119
+ --description "Core platform + services release pipeline" \
120
+ --json
121
+
122
+ # Confirm from the authoritative list envelope
123
+ sf devops project list --target-org my-devops-org --json | \
124
+ jq -r '.result.projects[] | select(.Id == "1Qg000000000001") | .Description'
125
+ ```
126
+
127
+ ---
128
+
129
+ ## Workflow 6: Update Multiple Fields at Once
130
+
131
+ **User request:** "Rename project 1Qg000000000002 to 'Beta Program' and update its description"
132
+
133
+ Pass every field in a single `update` call, then verify from the list envelope:
134
+
135
+ ```bash
136
+ sf devops project update \
137
+ --target-org my-devops-org \
138
+ --project-id 1Qg000000000002 \
139
+ --name "Beta Program" \
140
+ --description "Early-access beta feature pipeline" \
141
+ --json
142
+
143
+ sf devops project list --target-org my-devops-org --json | \
144
+ jq -r '.result.projects[] | select(.Id == "1Qg000000000002") | "\(.Name) — \(.Description)"'
145
+ ```
146
+
147
+ ---
148
+
149
+ ## Workflow 6b: Deactivate (Archive) a Project
150
+
151
+ **User request:** "Archive project 1Qg000000000002 — we're done with the beta"
152
+
153
+ **Steps:**
154
+
155
+ 1. **Deactivate the project**:
156
+ ```bash
157
+ sf devops project update \
158
+ --target-org my-devops-org \
159
+ --project-id 1Qg000000000002 \
160
+ --no-is-active \
161
+ --json
162
+ ```
163
+
164
+ 2. **Confirm** the project is inactive by re-reading the authoritative list envelope:
165
+ ```bash
166
+ sf devops project list --target-org my-devops-org --json | \
167
+ jq -r '.result.projects[] | select(.Id == "1Qg000000000002") | .IsActive'
168
+ ```
169
+ Output: `false`
170
+
171
+ > To reactivate later, run the same command with `--is-active` instead of `--no-is-active`.
172
+
173
+ ---
174
+
175
+ ## Workflow 7: Bootstrap — First Project in a Fresh Org
176
+
177
+ **User request:** "I just enabled DevOps Center. Get me started with a project."
178
+
179
+ **Steps:**
180
+
181
+ 1. **Confirm the org has DevOps Center and list existing projects**:
182
+ ```bash
183
+ sf devops project list --target-org my-devops-org --json | jq '.result.projects | length'
184
+ ```
185
+ Output: `0` (empty — no projects yet)
186
+
187
+ 2. **Create the first project**:
188
+ ```bash
189
+ sf devops project create \
190
+ --target-org my-devops-org \
191
+ --name "Main Release Pipeline" \
192
+ --description "Primary continuous delivery project" \
193
+ --json
194
+ ```
195
+
196
+ 3. **Report the project ID** and guide the user to the next step:
197
+ > Project created (ID: `1Qg000000000010`). Next, create a pipeline with `dx-devops-pipeline-manage` and work items with `dx-devops-work-item-manage`.
@@ -0,0 +1,295 @@
1
+ # DevOps Center Project CLI Commands Reference
2
+
3
+ Complete reference for `sf devops project` CLI commands with JSON output schemas and common patterns.
4
+
5
+ ## Command Summary
6
+
7
+ | Command | Purpose | Required Flags | Optional Flags |
8
+ |---------|---------|---------------|----------------|
9
+ | `sf devops project list` | List all DevOps Center projects | `--target-org` (`-o`) | `--api-version` |
10
+ | `sf devops project create` | Create a new project | `--target-org` (`-o`), `--name` (`-n`) | `--description` (`-d`), `--api-version` |
11
+ | `sf devops project update` | Update project name, description, or active status | `--target-org` (`-o`), `--project-id` (`-i`), plus at least one of: `--name` (`-n`), `--description` (`-d`), `--is-active` | `--api-version` |
12
+
13
+ All commands require `--target-org <alias>` (`-o`) unless the `target-org` config var is set, and support `--json` for structured output. `--flags-dir <value>` imports flag values from a directory.
14
+
15
+ **Org Authentication:**
16
+ Before running any DevOps Center commands, verify org authentication:
17
+ ```bash
18
+ sf org display --json
19
+ ```
20
+
21
+ If no default org is set or the user wants to target a specific org, add `--target-org <alias>` to all commands.
22
+
23
+ ---
24
+
25
+ ## List Projects
26
+
27
+ ### Basic Usage
28
+
29
+ ```bash
30
+ sf devops project list --target-org my-devops-org --json
31
+ ```
32
+
33
+ Queries the `DevopsProject` standard object and returns the Id, Name, and Description for each project.
34
+
35
+ ### Example
36
+
37
+ ```bash
38
+ # List projects using an org's username
39
+ sf devops project list --target-org devops-center@example.com --json
40
+ ```
41
+
42
+ ### JSON Output Schema
43
+
44
+ ```json
45
+ {
46
+ "status": 0,
47
+ "result": {
48
+ "projects": [
49
+ {
50
+ "Id": "1Qg000000000001",
51
+ "Name": "Project Alpha",
52
+ "Description": "Core platform release pipeline"
53
+ },
54
+ {
55
+ "Id": "1Qg000000000002",
56
+ "Name": "Project Beta",
57
+ "Description": null
58
+ }
59
+ ]
60
+ }
61
+ }
62
+ ```
63
+
64
+ The project records live under `.result.projects[]` (not a bare `.result[]` array) — every `jq` filter in this skill and its scripts reads that path.
65
+
66
+ ### Key Fields
67
+
68
+ - `Id`: Salesforce record ID for the project (use with `--project-id` in update and downstream skills)
69
+ - `Name`: Human-readable project name
70
+ - `Description`: Detailed description (may be null/blank)
71
+
72
+ ---
73
+
74
+ ## Create Project
75
+
76
+ ### Required Fields
77
+
78
+ ```bash
79
+ sf devops project create \
80
+ --target-org my-devops-org \
81
+ --name "MyApp Release" \
82
+ --json
83
+ ```
84
+
85
+ ### With Optional Description
86
+
87
+ ```bash
88
+ sf devops project create \
89
+ --target-org my-devops-org \
90
+ --name "Platform Update" \
91
+ --description "Platform services update" \
92
+ --json
93
+ ```
94
+
95
+ ### JSON Output Schema
96
+
97
+ ```json
98
+ {
99
+ "status": 0,
100
+ "result": {
101
+ "Id": "1Qg000000000003",
102
+ "Name": "Platform Update",
103
+ "Description": "Platform services update"
104
+ }
105
+ }
106
+ ```
107
+
108
+ > **Note:** The `create`/`update` single-record `result` shape is representative. The authoritative, verified envelope is `list` (`.result.projects[]` with capitalized `Id`/`Name`/`Description`). To obtain a created/updated project's ID reliably, re-read the list and filter by name rather than depending on the mutation command's own output shape — this is what `scripts/create-project.sh` does.
109
+
110
+ ---
111
+
112
+ ## Update Project
113
+
114
+ At least one of `--name`, `--description`, or `--is-active` must be provided.
115
+
116
+ ### Update Name
117
+
118
+ ```bash
119
+ sf devops project update \
120
+ --target-org my-devops-org \
121
+ --project-id 1Qg000000000001 \
122
+ --name "MyApp Release v2" \
123
+ --json
124
+ ```
125
+
126
+ ### Update Description
127
+
128
+ ```bash
129
+ sf devops project update \
130
+ --target-org my-devops-org \
131
+ --project-id 1Qg000000000001 \
132
+ --description "Updated release description" \
133
+ --json
134
+ ```
135
+
136
+ ### Activate / Deactivate
137
+
138
+ ```bash
139
+ # Deactivate a project
140
+ sf devops project update \
141
+ --target-org my-devops-org \
142
+ --project-id 1Qg000000000001 \
143
+ --no-is-active \
144
+ --json
145
+
146
+ # Activate a project
147
+ sf devops project update \
148
+ --target-org my-devops-org \
149
+ --project-id 1Qg000000000001 \
150
+ --is-active \
151
+ --json
152
+ ```
153
+
154
+ > **Note:** `--is-active` is a boolean flag. Use `--is-active` to activate or `--no-is-active` to deactivate — never pass a value like `--is-active true`.
155
+
156
+ ### Update Multiple Fields at Once
157
+
158
+ ```bash
159
+ sf devops project update \
160
+ --target-org my-devops-org \
161
+ --project-id 1Qg000000000001 \
162
+ --name "Archived App" \
163
+ --description "Archived" \
164
+ --no-is-active \
165
+ --json
166
+ ```
167
+
168
+ ### JSON Output Schema
169
+
170
+ ```json
171
+ {
172
+ "status": 0,
173
+ "result": {
174
+ "Id": "1Qg000000000001",
175
+ "Name": "MyApp Release v2",
176
+ "Description": "Updated release description",
177
+ "IsActive": true
178
+ }
179
+ }
180
+ ```
181
+
182
+ ---
183
+
184
+ ## Error Handling
185
+
186
+ ### Common Error Scenarios
187
+
188
+ **Project not found (update):**
189
+ ```json
190
+ {
191
+ "status": 1,
192
+ "name": "NOT_FOUND",
193
+ "message": "Project with ID 1Qg000000000999 does not exist or is not accessible",
194
+ "exitCode": 1
195
+ }
196
+ ```
197
+
198
+ **Missing required field (create):**
199
+ ```json
200
+ {
201
+ "status": 1,
202
+ "name": "RequiredFlagsError",
203
+ "message": "Missing required flag --name",
204
+ "exitCode": 1
205
+ }
206
+ ```
207
+
208
+ **Missing update field:**
209
+ ```json
210
+ {
211
+ "status": 1,
212
+ "name": "RequiredFlagsError",
213
+ "message": "At least one of --name, --description, or --is-active must be provided",
214
+ "exitCode": 1
215
+ }
216
+ ```
217
+
218
+ **DevOps Center not enabled / no projects accessible:**
219
+ ```json
220
+ {
221
+ "status": 1,
222
+ "name": "DEVOPS_NOT_ENABLED",
223
+ "message": "DevOps Center is not enabled for this org",
224
+ "exitCode": 1
225
+ }
226
+ ```
227
+
228
+ **Authentication failure:**
229
+ ```json
230
+ {
231
+ "status": 1,
232
+ "name": "NoOrgFound",
233
+ "message": "No org configuration found for target-org. Run 'sf org login web' to authenticate.",
234
+ "exitCode": 1
235
+ }
236
+ ```
237
+
238
+ ---
239
+
240
+ ## Parsing JSON Output
241
+
242
+ Every filter reads the authoritative `.result.projects[]` envelope. To resolve a name to an ID or read back a created project's ID, filter the list by name (see the Idempotent Create Pattern below and `scripts/list-projects.sh --resolve`).
243
+
244
+ ### Check for Empty List
245
+
246
+ ```bash
247
+ COUNT=$(sf devops project list --target-org my-devops-org --json | jq '.result.projects | length')
248
+
249
+ if [ "$COUNT" -eq 0 ]; then
250
+ echo "No projects found — create one before setting up work items"
251
+ else
252
+ echo "Found $COUNT projects"
253
+ fi
254
+ ```
255
+
256
+ ### List Project IDs and Names
257
+
258
+ ```bash
259
+ sf devops project list --target-org my-devops-org --json | \
260
+ jq -r '.result.projects[] | "\(.Id): \(.Name)"'
261
+
262
+ # Output:
263
+ # 1Qg000000000001: Project Alpha
264
+ # 1Qg000000000002: Project Beta
265
+ ```
266
+
267
+ ---
268
+
269
+ ## Idempotent Create Pattern
270
+
271
+ To avoid duplicate projects, check for an existing project with the same name before creating:
272
+
273
+ ```bash
274
+ NAME="MyApp Release"
275
+
276
+ # Check if a project with this name exists
277
+ EXISTING_ID=$(sf devops project list --target-org my-devops-org --json | \
278
+ jq -r ".result.projects[] | select(.Name == \"$NAME\") | .Id" | head -n1)
279
+
280
+ if [ -n "$EXISTING_ID" ]; then
281
+ echo "Project already exists: $EXISTING_ID"
282
+ else
283
+ # Create new project, then read the ID back from the list
284
+ sf devops project create --target-org my-devops-org --name "$NAME" --json >/dev/null
285
+ NEW_ID=$(sf devops project list --target-org my-devops-org --json | \
286
+ jq -r ".result.projects[] | select(.Name == \"$NAME\") | .Id" | head -n1)
287
+ echo "Created new project: $NEW_ID"
288
+ fi
289
+ ```
290
+
291
+ ---
292
+
293
+ ## Authentication Requirements
294
+
295
+ All `sf devops project` commands require an authenticated org (`sf org login web` or JWT), DevOps Center enabled (DOCe provisioned), and permission to manage projects. Verify with `sf org display --target-org <alias> --json`; if auth fails, run `sf org login web --set-default --alias <alias>`.
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env bash
2
+ # Deterministically create a DevOps Center project, idempotently: if a project
3
+ # with the same name already exists, return its ID instead of creating a
4
+ # duplicate. Verifies success by re-reading the project list, so it never
5
+ # depends on the create command's own output envelope.
6
+ # Usage:
7
+ # scripts/create-project.sh <name> [description] [target-org]
8
+ # Prints "EXISTING <id>" or "CREATED <id>" on success; exits 2 on error.
9
+
10
+ set -euo pipefail
11
+
12
+ NAME="${1:?Usage: create-project.sh <name> [description] [target-org]}"
13
+ DESC="${2:-}"
14
+ ORG="${3:-}"
15
+ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16
+
17
+ # Idempotency preflight. list-projects.sh --resolve exits 0 (found), 3 (no such
18
+ # project), or 2 (auth / CLI / JSON failure). Only a clean "not found" (3) is
19
+ # safe to proceed on — any other failure means the list could not be read, so we
20
+ # must abort rather than risk a duplicate or writing to an unreadable org.
21
+ err=$(mktemp); rc=0
22
+ EXISTING=$("$HERE/list-projects.sh" --resolve "$NAME" "$ORG" 2>"$err") || rc=$?
23
+ if [ "$rc" -eq 0 ]; then
24
+ rm -f "$err"; echo "EXISTING $EXISTING"; exit 0
25
+ elif [ "$rc" -ne 3 ]; then
26
+ echo "ERROR: idempotency preflight failed (exit $rc); aborting create to avoid a duplicate or writing to an org whose project list could not be read: $(tr '\n' ' ' <"$err")" >&2
27
+ rm -f "$err"; exit "$rc"
28
+ fi
29
+ rm -f "$err"
30
+ # rc == 3: no existing project with this name — safe to create.
31
+
32
+ flag=(); [ -n "$ORG" ] && flag=(--target-org "$ORG")
33
+ dflag=(); [ -n "$DESC" ] && dflag=(--description "$DESC")
34
+
35
+ err=$(mktemp); rc=0
36
+ sf devops project create --name "$NAME" "${dflag[@]+"${dflag[@]}"}" "${flag[@]+"${flag[@]}"}" --json >/dev/null 2>"$err" || rc=$?
37
+ if [ "$rc" -ne 0 ]; then
38
+ echo "ERROR: project create failed (sf exited $rc): $(tr '\n' ' ' <"$err")" >&2
39
+ rm -f "$err"; exit 2
40
+ fi
41
+ rm -f "$err"
42
+
43
+ # Verify by re-reading the list (authoritative .result.projects[] envelope).
44
+ if ID=$("$HERE/list-projects.sh" --resolve "$NAME" "$ORG"); then
45
+ echo "CREATED $ID"; exit 0
46
+ fi
47
+ echo "ERROR: create reported success but project '$NAME' is not in the project list" >&2
48
+ exit 2
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env bash
2
+ # Deterministically list DevOps Center projects, or resolve a single project
3
+ # name to its ID. Handles the empty-list case explicitly.
4
+ # Usage:
5
+ # scripts/list-projects.sh [target-org]
6
+ # -> print "Id<TAB>Name<TAB>Description" for every project (one per line);
7
+ # prints "NO_PROJECTS" to stdout and exits 0 when none exist
8
+ # scripts/list-projects.sh --resolve <project-name> [target-org]
9
+ # -> print the matching project's Id on stdout; exits 3 if not found
10
+ # Exits 2 on any CLI read / JSON error.
11
+ #
12
+ # project list returns SObject records under .result.projects[] with capitalized
13
+ # fields (Id, Name, Description).
14
+
15
+ set -euo pipefail
16
+
17
+ read_projects() {
18
+ local org="$1" flag=() err rc json st
19
+ [ -n "$org" ] && flag=(--target-org "$org")
20
+ err=$(mktemp); rc=0
21
+ json=$(sf devops project list "${flag[@]+"${flag[@]}"}" --json 2>"$err") || rc=$?
22
+ if [ "$rc" -ne 0 ]; then
23
+ echo "ERROR: could not list projects (sf exited $rc): $(tr '\n' ' ' <"$err")" >&2
24
+ rm -f "$err"; exit 2
25
+ fi
26
+ rm -f "$err"
27
+ st=$(echo "$json" | jq -r '.status // 1' 2>/dev/null || echo 1)
28
+ if [ "$st" != "0" ]; then
29
+ local msg; msg=$(echo "$json" | jq -r '.message // "unknown error"' 2>/dev/null || echo "unparseable response")
30
+ echo "ERROR: 'project list' returned status $st — $msg" >&2; exit 2
31
+ fi
32
+ printf '%s' "$json"
33
+ }
34
+
35
+ if [ "${1:-}" = "--resolve" ]; then
36
+ NAME="${2:?--resolve needs a project name}"; ORG="${3:-}"
37
+ JSON=$(read_projects "$ORG")
38
+ ID=$(echo "$JSON" | jq -r --arg n "$NAME" '.result.projects[]? | select(.Name == $n) | .Id' | head -n1)
39
+ if [ -z "$ID" ] || [ "$ID" = "null" ]; then
40
+ echo "ERROR: no project named '$NAME' found" >&2; exit 3
41
+ fi
42
+ echo "$ID"; exit 0
43
+ fi
44
+
45
+ ORG="${1:-}"
46
+ JSON=$(read_projects "$ORG")
47
+ COUNT=$(echo "$JSON" | jq '.result.projects | length')
48
+ if [ "$COUNT" -eq 0 ]; then
49
+ echo "NO_PROJECTS"; exit 0
50
+ fi
51
+ echo "$JSON" | jq -r '.result.projects[] | "\(.Id)\t\(.Name)\t\(.Description // "")"'
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env bash
2
+ # Deterministically update a DevOps Center project's name, description, and/or
3
+ # active status. Accepts a project ID or a project name (resolved via the list).
4
+ # At least one of --name / --description / --is-active|--no-is-active is required.
5
+ # Usage:
6
+ # scripts/update-project.sh --project (<id>|name:<name>) \
7
+ # [--name <new-name>] [--description <new-desc>] \
8
+ # [--is-active|--no-is-active] [--target-org <alias>]
9
+ # Prints "UPDATED <id>" on success; exits 2 on CLI error, 3 if the name cannot
10
+ # be resolved, 1 on usage error.
11
+
12
+ set -euo pipefail
13
+
14
+ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
+ PROJECT="" NEW_NAME="" NEW_DESC="" ACTIVE="" ORG=""
16
+ have_name=0 have_desc=0
17
+
18
+ while [ $# -gt 0 ]; do
19
+ case "$1" in
20
+ --project) PROJECT="${2:?}"; shift 2 ;;
21
+ --name) NEW_NAME="${2:?}"; have_name=1; shift 2 ;;
22
+ --description) NEW_DESC="${2:?}"; have_desc=1; shift 2 ;;
23
+ --is-active) ACTIVE="true"; shift ;;
24
+ --no-is-active) ACTIVE="false"; shift ;;
25
+ --target-org) ORG="${2:?}"; shift 2 ;;
26
+ *) echo "ERROR: unknown arg '$1'" >&2; exit 1 ;;
27
+ esac
28
+ done
29
+
30
+ [ -n "$PROJECT" ] || { echo "ERROR: --project (<id>|name:<name>) is required" >&2; exit 1; }
31
+ if [ "$have_name" -eq 0 ] && [ "$have_desc" -eq 0 ] && [ -z "$ACTIVE" ]; then
32
+ echo "ERROR: at least one of --name, --description, or --is-active/--no-is-active is required" >&2; exit 1
33
+ fi
34
+
35
+ # Resolve name:<name> to an ID; otherwise treat as a literal ID. list-projects.sh
36
+ # --resolve exits 3 (no such project) or 2 (auth / CLI / JSON failure); propagate
37
+ # the real code so a failed read is never masked as a clean "not found".
38
+ case "$PROJECT" in
39
+ name:*)
40
+ rrc=0
41
+ PID=$("$HERE/list-projects.sh" --resolve "${PROJECT#name:}" "$ORG") || rrc=$?
42
+ [ "$rrc" -eq 0 ] || exit "$rrc"
43
+ ;;
44
+ *) PID="$PROJECT" ;;
45
+ esac
46
+
47
+ flag=(); [ -n "$ORG" ] && flag=(--target-org "$ORG")
48
+ args=(--project-id "$PID")
49
+ [ "$have_name" -eq 1 ] && args+=(--name "$NEW_NAME")
50
+ [ "$have_desc" -eq 1 ] && args+=(--description "$NEW_DESC")
51
+ [ "$ACTIVE" = "true" ] && args+=(--is-active)
52
+ [ "$ACTIVE" = "false" ] && args+=(--no-is-active)
53
+
54
+ err=$(mktemp); rc=0
55
+ sf devops project update "${args[@]}" "${flag[@]+"${flag[@]}"}" --json >/dev/null 2>"$err" || rc=$?
56
+ if [ "$rc" -ne 0 ]; then
57
+ echo "ERROR: project update failed (sf exited $rc): $(tr '\n' ' ' <"$err")" >&2
58
+ rm -f "$err"; exit 2
59
+ fi
60
+ rm -f "$err"
61
+
62
+ # Verify persistence: re-read the project from the authoritative
63
+ # .result.projects[] list envelope and assert each requested field took effect.
64
+ # Never trust the update command's own exit code / output shape alone.
65
+ verr=$(mktemp); vrc=0
66
+ LIST=$(sf devops project list "${flag[@]+"${flag[@]}"}" --json 2>"$verr") || vrc=$?
67
+ if [ "$vrc" -ne 0 ]; then
68
+ echo "ERROR: update succeeded but the verification re-read failed (sf exited $vrc): $(tr '\n' ' ' <"$verr")" >&2
69
+ rm -f "$verr"; exit 2
70
+ fi
71
+ rm -f "$verr"
72
+
73
+ REC=$(echo "$LIST" | jq -c --arg id "$PID" '.result.projects[]? | select(.Id == $id)')
74
+ if [ -z "$REC" ]; then
75
+ echo "ERROR: update reported success but project '$PID' is not in the project list" >&2; exit 2
76
+ fi
77
+
78
+ if [ "$have_name" -eq 1 ]; then
79
+ GOT=$(echo "$REC" | jq -r '.Name')
80
+ [ "$GOT" = "$NEW_NAME" ] || { echo "ERROR: name not persisted (expected '$NEW_NAME', got '$GOT')" >&2; exit 2; }
81
+ fi
82
+ if [ "$have_desc" -eq 1 ]; then
83
+ GOT=$(echo "$REC" | jq -r '.Description // ""')
84
+ [ "$GOT" = "$NEW_DESC" ] || { echo "ERROR: description not persisted (expected '$NEW_DESC', got '$GOT')" >&2; exit 2; }
85
+ fi
86
+ if [ -n "$ACTIVE" ]; then
87
+ # The list envelope exposes IsActive only on some API versions. Assert it when
88
+ # present; when absent (null), the field is not verifiable from the list, so we
89
+ # fall back to the update command's success (already confirmed above) for it.
90
+ GOT=$(echo "$REC" | jq -r '.IsActive // "absent"')
91
+ if [ "$GOT" != "absent" ] && [ "$GOT" != "$ACTIVE" ]; then
92
+ echo "ERROR: active status not persisted (expected '$ACTIVE', got '$GOT')" >&2; exit 2
93
+ fi
94
+ fi
95
+
96
+ echo "UPDATED $PID"; exit 0