scc-universal 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/.cursor/agents/sf-agentforce-agent.md +88 -40
- package/.cursor/skills/prompt-optimizer/SKILL.md +21 -21
- package/.cursor/skills/sf-2gp-security-review/SKILL.md +167 -0
- package/.cursor/skills/sf-agentforce-development/SKILL.md +385 -348
- package/.cursor/skills/sf-cli-reference/SKILL.md +221 -0
- package/.cursor/skills/sf-harness-audit/SKILL.md +2 -2
- package/.cursor/skills/sf-quickstart/SKILL.md +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/README.md +8 -38
- package/agents/sf-agentforce-agent.md +88 -40
- package/docs/ARCHITECTURE.md +4 -3
- package/docs/authoring-guide.md +1 -1
- package/docs/hook-development.md +1 -1
- package/examples/agentforce-action/README.md +4 -4
- package/examples/devops-pipeline/README.md +4 -4
- package/examples/integration-pattern/README.md +4 -4
- package/examples/platform-events/README.md +4 -4
- package/examples/security-audit/README.md +3 -3
- package/examples/visualforce-migration/README.md +4 -4
- package/manifests/install-modules.json +9 -3
- package/package.json +2 -2
- package/scripts/lib/install-executor.js +23 -12
- package/skills/_reference/AGENTFORCE_PATTERNS.md +433 -51
- package/skills/_reference/APPEXCHANGE_REVIEW.md +427 -0
- package/skills/_reference/SF_CLI_COMMANDS.md +812 -0
- package/skills/prompt-optimizer/SKILL.md +21 -21
- package/skills/sf-2gp-security-review/SKILL.md +168 -0
- package/skills/sf-agentforce-development/SKILL.md +385 -348
- package/skills/sf-cli-reference/SKILL.md +225 -0
- package/skills/sf-harness-audit/SKILL.md +2 -2
- package/skills/sf-quickstart/SKILL.md +1 -1
- package/.cursor/hooks/adapter.js +0 -81
- package/.cursor/hooks/after-file-edit.js +0 -26
- package/.cursor/hooks/after-mcp-execution.js +0 -12
- package/.cursor/hooks/after-shell-execution.js +0 -30
- package/.cursor/hooks/after-tab-file-edit.js +0 -12
- package/.cursor/hooks/before-mcp-execution.js +0 -11
- package/.cursor/hooks/before-read-file.js +0 -13
- package/.cursor/hooks/before-shell-execution.js +0 -29
- package/.cursor/hooks/before-submit-prompt.js +0 -23
- package/.cursor/hooks/pre-compact.js +0 -7
- package/.cursor/hooks/session-end.js +0 -10
- package/.cursor/hooks/session-start.js +0 -10
- package/.cursor/hooks/stop.js +0 -18
- package/.cursor/hooks/subagent-start.js +0 -10
- package/.cursor/hooks/subagent-stop.js +0 -10
|
@@ -308,7 +308,7 @@ public with sharing class AccountEditorLwcController {
|
|
|
308
308
|
|
|
309
309
|
## SCC Skills
|
|
310
310
|
|
|
311
|
-
-
|
|
312
|
-
-
|
|
313
|
-
-
|
|
314
|
-
-
|
|
311
|
+
- `sf-visualforce-development` -- audit a Visualforce page for migration readiness
|
|
312
|
+
- `sf-lwc-development` -- review the migrated LWC component for best practices
|
|
313
|
+
- `sf-apex-best-practices` -- review the simplified Apex controller
|
|
314
|
+
- `sf-security` -- verify security enforcement in the new component
|
|
@@ -24,8 +24,12 @@
|
|
|
24
24
|
"targets": { "claude": ".claude/skills/", "cursor": ".cursor/skills/" }
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
|
-
"paths": ["scripts/hooks/"],
|
|
28
|
-
"
|
|
27
|
+
"paths": ["scripts/hooks/", "scripts/lib/"],
|
|
28
|
+
"destMap": { "hooks": "scripts" },
|
|
29
|
+
"includeOnly": {
|
|
30
|
+
"scripts/lib/": ["utils.js", "hook-input.js", "apex-analysis.js", "hook-flags.js"]
|
|
31
|
+
},
|
|
32
|
+
"targets": { "claude": ".claude/hooks/", "cursor": ".cursor/hooks/" },
|
|
29
33
|
"installType": "hooks",
|
|
30
34
|
"hooksSource": "hooks/hooks.json"
|
|
31
35
|
}
|
|
@@ -151,7 +155,8 @@
|
|
|
151
155
|
"paths": [
|
|
152
156
|
"skills/sf-devops-ci-cd/",
|
|
153
157
|
"skills/sf-deployment/",
|
|
154
|
-
"skills/sf-deployment-constraints/"
|
|
158
|
+
"skills/sf-deployment-constraints/",
|
|
159
|
+
"skills/sf-cli-reference/"
|
|
155
160
|
],
|
|
156
161
|
"targets": { "claude": ".claude/skills/", "cursor": ".cursor/skills/" }
|
|
157
162
|
}
|
|
@@ -169,6 +174,7 @@
|
|
|
169
174
|
{
|
|
170
175
|
"paths": [
|
|
171
176
|
"skills/sf-security/",
|
|
177
|
+
"skills/sf-2gp-security-review/",
|
|
172
178
|
"skills/sf-governor-limits/",
|
|
173
179
|
"skills/sf-soql-optimization/",
|
|
174
180
|
"skills/sf-security-constraints/"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scc-universal",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Complete collection of production-ready Salesforce agents, skills, hooks, and MCP configurations for Claude Code and other AI harnesses. Salesforce Claude Code (SCC) — your AI-powered Salesforce development partner.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"salesforce",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"build:cursor-agents": "node scripts/dev/build-cursor-agents.js",
|
|
67
67
|
"test": "npm run build && node scripts/ci/validate-agents.js && node scripts/ci/validate-commands.js && node scripts/ci/validate-skills.js && node scripts/ci/validate-hooks.js && node scripts/ci/validate-install-manifests.js && node scripts/ci/validate-no-personal-paths.js && node tests/run-all.js",
|
|
68
68
|
"smoke": "bash scripts/ci/smoke-test.sh",
|
|
69
|
-
"lint": "eslint . && markdownlint '**/*.md' --ignore node_modules",
|
|
69
|
+
"lint": "eslint . && markdownlint '**/*.md' --ignore node_modules --ignore CHANGELOG.md",
|
|
70
70
|
"coverage": "c8 --all --include=\"scripts/**/*.js\" --exclude=\"scripts/scc.js\" --reporter=text --reporter=lcov --check-coverage --lines 80 --functions 80 --branches 80 --statements 80 node tests/run-all.js",
|
|
71
71
|
"harness:audit": "node scripts/dev/harness-audit.js",
|
|
72
72
|
"orchestrate:status": "node scripts/dev/orchestration-status.js",
|
|
@@ -144,7 +144,7 @@ function isAgentFile(srcRelative) {
|
|
|
144
144
|
* @param {string} targetName - install target ('claude' or 'cursor')
|
|
145
145
|
* @returns {Array} installed file records
|
|
146
146
|
*/
|
|
147
|
-
function installPaths(pathsList, destDir, pluginRoot, moduleName, dryRun, targetName) {
|
|
147
|
+
function installPaths(pathsList, destDir, pluginRoot, moduleName, dryRun, targetName, destMap, includeOnly) {
|
|
148
148
|
const installed = [];
|
|
149
149
|
|
|
150
150
|
for (const srcRelative of pathsList) {
|
|
@@ -157,7 +157,11 @@ function installPaths(pathsList, destDir, pluginRoot, moduleName, dryRun, target
|
|
|
157
157
|
continue;
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
let dirName = path.basename(srcRelative.slice(0, -1));
|
|
161
|
+
// Allow manifest destMap to override the destination directory name
|
|
162
|
+
if (destMap && destMap[dirName]) {
|
|
163
|
+
dirName = destMap[dirName];
|
|
164
|
+
}
|
|
161
165
|
const destSubDir = path.join(destDir, dirName);
|
|
162
166
|
|
|
163
167
|
// Use skill adapter for Cursor target when source is a skill directory
|
|
@@ -171,8 +175,11 @@ function installPaths(pathsList, destDir, pluginRoot, moduleName, dryRun, target
|
|
|
171
175
|
continue;
|
|
172
176
|
}
|
|
173
177
|
|
|
178
|
+
// Filter files if includeOnly is specified for this source directory
|
|
179
|
+
const allowList = includeOnly && includeOnly[srcRelative];
|
|
174
180
|
const entries = fs.readdirSync(srcPath);
|
|
175
181
|
for (const entry of entries) {
|
|
182
|
+
if (allowList && !allowList.includes(entry)) continue;
|
|
176
183
|
const fullSrc = path.join(srcPath, entry);
|
|
177
184
|
if (fs.statSync(fullSrc).isFile()) {
|
|
178
185
|
const record = installFile(fullSrc, destSubDir, entry, moduleName, dryRun);
|
|
@@ -201,7 +208,11 @@ function installPaths(pathsList, destDir, pluginRoot, moduleName, dryRun, target
|
|
|
201
208
|
|
|
202
209
|
/**
|
|
203
210
|
* Remap hook commands from plugin paths to project-local paths.
|
|
204
|
-
* ${CLAUDE_PLUGIN_ROOT}/scripts/hooks/foo.js → "$CLAUDE_PROJECT_DIR"/.claude/hooks/foo.js
|
|
211
|
+
* ${CLAUDE_PLUGIN_ROOT}/scripts/hooks/foo.js → "$CLAUDE_PROJECT_DIR"/.claude/hooks/scripts/foo.js
|
|
212
|
+
*
|
|
213
|
+
* Install copies scripts/hooks/ → .claude/hooks/scripts/ (via destMap) and
|
|
214
|
+
* scripts/lib/ → .claude/hooks/lib/ so that require('../lib/...') resolves
|
|
215
|
+
* correctly from the installed location.
|
|
205
216
|
*/
|
|
206
217
|
function remapHookCommandForProject(command) {
|
|
207
218
|
// Strip run-with-flags wrapper and extract the actual script
|
|
@@ -209,7 +220,7 @@ function remapHookCommandForProject(command) {
|
|
|
209
220
|
/node\s+"?\$\{CLAUDE_PLUGIN_ROOT\}\/scripts\/hooks\/run-with-flags\.js"?\s+\S+\s+\S+\s+"?\$\{CLAUDE_PLUGIN_ROOT\}\/scripts\/hooks\/([^"]+)"?/
|
|
210
221
|
);
|
|
211
222
|
if (runWithFlagsMatch) {
|
|
212
|
-
return `node "$CLAUDE_PROJECT_DIR"/.claude/hooks/${runWithFlagsMatch[1]}`;
|
|
223
|
+
return `node "$CLAUDE_PROJECT_DIR"/.claude/hooks/scripts/${runWithFlagsMatch[1]}`;
|
|
213
224
|
}
|
|
214
225
|
|
|
215
226
|
// Shell flags wrapper
|
|
@@ -217,7 +228,7 @@ function remapHookCommandForProject(command) {
|
|
|
217
228
|
/bash\s+"?\$\{CLAUDE_PLUGIN_ROOT\}\/scripts\/hooks\/run-with-flags-shell\.sh"?\s+\S+\s+"?scripts\/hooks\/([^"]+)"?\s+\S+/
|
|
218
229
|
);
|
|
219
230
|
if (shellFlagsMatch) {
|
|
220
|
-
return `bash "$CLAUDE_PROJECT_DIR"/.claude/hooks/${shellFlagsMatch[1]}`;
|
|
231
|
+
return `bash "$CLAUDE_PROJECT_DIR"/.claude/hooks/scripts/${shellFlagsMatch[1]}`;
|
|
221
232
|
}
|
|
222
233
|
|
|
223
234
|
// Direct script reference
|
|
@@ -225,7 +236,7 @@ function remapHookCommandForProject(command) {
|
|
|
225
236
|
/node\s+"?\$\{CLAUDE_PLUGIN_ROOT\}\/scripts\/hooks\/([^"]+)"?/
|
|
226
237
|
);
|
|
227
238
|
if (directMatch) {
|
|
228
|
-
return `node "$CLAUDE_PROJECT_DIR"/.claude/hooks/${directMatch[1]}`;
|
|
239
|
+
return `node "$CLAUDE_PROJECT_DIR"/.claude/hooks/scripts/${directMatch[1]}`;
|
|
229
240
|
}
|
|
230
241
|
|
|
231
242
|
// npx commands pass through
|
|
@@ -233,7 +244,7 @@ function remapHookCommandForProject(command) {
|
|
|
233
244
|
return command;
|
|
234
245
|
}
|
|
235
246
|
|
|
236
|
-
return command.replace(/\$\{CLAUDE_PLUGIN_ROOT\}\/scripts\/hooks\//g, '"$CLAUDE_PROJECT_DIR"/.claude/hooks/');
|
|
247
|
+
return command.replace(/\$\{CLAUDE_PLUGIN_ROOT\}\/scripts\/hooks\//g, '"$CLAUDE_PROJECT_DIR"/.claude/hooks/scripts/');
|
|
237
248
|
}
|
|
238
249
|
|
|
239
250
|
/**
|
|
@@ -256,7 +267,7 @@ function installHooks(group, pluginRoot, targetName, projectRoot, moduleName, dr
|
|
|
256
267
|
const destRelative = (group.targets || {})[targetName];
|
|
257
268
|
if (destRelative) {
|
|
258
269
|
const destDir = path.join(projectRoot, destRelative);
|
|
259
|
-
installed.push(...installPaths(group.paths || [], destDir, pluginRoot, moduleName, dryRun, targetName));
|
|
270
|
+
installed.push(...installPaths(group.paths || [], destDir, pluginRoot, moduleName, dryRun, targetName, group.destMap, group.includeOnly));
|
|
260
271
|
}
|
|
261
272
|
|
|
262
273
|
// Step 2: For Claude Code target, merge hooks into .claude/settings.json
|
|
@@ -318,13 +329,13 @@ function installHooks(group, pluginRoot, targetName, projectRoot, moduleName, dr
|
|
|
318
329
|
const cursorHooksPath = path.join(projectRoot, '.cursor', 'hooks.json');
|
|
319
330
|
const cursorHooks = transformHooks(hooksJson);
|
|
320
331
|
|
|
321
|
-
// Remap adapter paths from scripts/hooks/ to .cursor/hooks/
|
|
322
|
-
// (adapter outputs plugin-relative paths, but install copies to .cursor/hooks/)
|
|
332
|
+
// Remap adapter paths from scripts/hooks/ to .cursor/hooks/scripts/
|
|
333
|
+
// (adapter outputs plugin-relative paths, but install copies to .cursor/hooks/scripts/)
|
|
323
334
|
for (const hooks of Object.values(cursorHooks.hooks)) {
|
|
324
335
|
for (const hook of hooks) {
|
|
325
336
|
if (hook.command) {
|
|
326
|
-
hook.command = hook.command.replace(/\bnode scripts\/hooks\//g, 'node "$CURSOR_PROJECT_DIR"/.cursor/hooks/');
|
|
327
|
-
hook.command = hook.command.replace(/\bbash scripts\/hooks\//g, 'bash "$CURSOR_PROJECT_DIR"/.cursor/hooks/');
|
|
337
|
+
hook.command = hook.command.replace(/\bnode scripts\/hooks\//g, 'node "$CURSOR_PROJECT_DIR"/.cursor/hooks/scripts/');
|
|
338
|
+
hook.command = hook.command.replace(/\bbash scripts\/hooks\//g, 'bash "$CURSOR_PROJECT_DIR"/.cursor/hooks/scripts/');
|
|
328
339
|
}
|
|
329
340
|
}
|
|
330
341
|
}
|