scc-universal 1.2.1 → 1.2.2
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/skills/prompt-optimizer/SKILL.md +21 -21
- 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/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 +6 -2
- package/package.json +2 -2
- package/scripts/lib/install-executor.js +23 -12
- package/skills/prompt-optimizer/SKILL.md +21 -21
- 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
|
@@ -93,13 +93,13 @@ Map intent + scope + tech stack (from Phase 0) to specific SCC components.
|
|
|
93
93
|
|
|
94
94
|
| Intent | Invocable Skills | Skills | Agents |
|
|
95
95
|
|--------|----------|--------|--------|
|
|
96
|
-
| New Feature |
|
|
97
|
-
| Bug Fix |
|
|
98
|
-
| Refactor | /refactor-clean,
|
|
99
|
-
| Testing |
|
|
100
|
-
| Review |
|
|
96
|
+
| New Feature | sf-tdd-workflow, sf-apex-best-practices | sf-apex-best-practices, sf-apex-enterprise-patterns | sf-architect, sf-apex-agent, sf-review-agent |
|
|
97
|
+
| Bug Fix | sf-tdd-workflow, sf-build-fix | sf-apex-testing, sf-debugging | sf-bugfix-agent, sf-apex-agent |
|
|
98
|
+
| Refactor | /refactor-clean, sf-apex-best-practices | sf-trigger-frameworks, sf-apex-enterprise-patterns | refactor-cleaner, sf-review-agent |
|
|
99
|
+
| Testing | sf-tdd-workflow, sf-apex-testing, sf-e2e-testing | sf-apex-testing, sf-tdd-workflow | sf-apex-agent |
|
|
100
|
+
| Review | sf-apex-best-practices, sf-lwc-development, sf-security | sf-security | sf-review-agent, sf-review-agent |
|
|
101
101
|
| Documentation | /update-docs | — | doc-updater, deep-researcher |
|
|
102
|
-
| Infrastructure |
|
|
102
|
+
| Infrastructure | sf-deployment | sf-devops-ci-cd, sf-deployment | sf-architect |
|
|
103
103
|
| Design (EPIC) | — | — | sf-architect, sf-architect |
|
|
104
104
|
|
|
105
105
|
#### By Tech Stack
|
|
@@ -161,7 +161,7 @@ For tasks that exceed a single session, split into sequential prompts:
|
|
|
161
161
|
|
|
162
162
|
- Prompt 1: Research + Plan (use search-first skill, then sf-architect agent)
|
|
163
163
|
- Prompt 2-N: Implement one phase per prompt (each ends with sf-review-agent agent)
|
|
164
|
-
- Final Prompt: Integration test +
|
|
164
|
+
- Final Prompt: Integration test + sf-apex-best-practices across all phases
|
|
165
165
|
- Use /save-session and /resume-session to preserve context between sessions
|
|
166
166
|
|
|
167
167
|
---
|
|
@@ -188,7 +188,7 @@ If Phase 0 auto-detected the answer, state it instead of asking.
|
|
|
188
188
|
|
|
189
189
|
| Type | Component | Purpose |
|
|
190
190
|
|------|-----------|---------|
|
|
191
|
-
| Command |
|
|
191
|
+
| Command | sf-tdd-workflow | TDD workflow for Apex |
|
|
192
192
|
| Skill | sf-apex-best-practices | Apex coding standards |
|
|
193
193
|
| Agent | sf-review-agent | Post-implementation review |
|
|
194
194
|
| Model | Sonnet | Recommended for this scope |
|
|
@@ -206,7 +206,7 @@ The prompt must be self-contained and ready to copy-paste. Include:
|
|
|
206
206
|
- Scope boundaries (what NOT to do)
|
|
207
207
|
|
|
208
208
|
For items that reference blueprint, write: "Use the sf-architect agent to..."
|
|
209
|
-
(not
|
|
209
|
+
(not `sf-architect agent`, since sf-architect is an agent, not a command).
|
|
210
210
|
|
|
211
211
|
### Section 4: Optimized Prompt — Quick Version
|
|
212
212
|
|
|
@@ -214,12 +214,12 @@ A compact version for experienced SCC users. Vary by intent type:
|
|
|
214
214
|
|
|
215
215
|
| Intent | Quick Pattern |
|
|
216
216
|
|--------|--------------|
|
|
217
|
-
| New Feature | `Use sf-architect agent for [feature].
|
|
218
|
-
| Bug Fix |
|
|
219
|
-
| Refactor | `/refactor-clean [scope].
|
|
217
|
+
| New Feature | `Use sf-architect agent for [feature]. sf-tdd-workflow to implement. sf-apex-best-practices. Use sf-review-agent agent.` |
|
|
218
|
+
| Bug Fix | `sf-tdd-workflow — write failing test for [bug]. Fix to green. Use sf-review-agent agent.` |
|
|
219
|
+
| Refactor | `/refactor-clean [scope]. sf-apex-best-practices. Use sf-review-agent agent.` |
|
|
220
220
|
| Research | `Use search-first skill for [topic]. Use sf-architect agent based on findings.` |
|
|
221
|
-
| Testing |
|
|
222
|
-
| Review |
|
|
221
|
+
| Testing | `sf-tdd-workflow [class]. sf-e2e-testing for critical flows. sf-apex-testing.` |
|
|
222
|
+
| Review | `sf-apex-best-practices. Then use sf-review-agent agent.` |
|
|
223
223
|
| Docs | `/update-docs. Use deep-researcher agent.` |
|
|
224
224
|
| EPIC | `Use sf-architect agent for "[objective]". Execute phases with sf-review-agent agent gates.` |
|
|
225
225
|
|
|
@@ -267,9 +267,9 @@ Technical requirements:
|
|
|
267
267
|
|
|
268
268
|
Workflow:
|
|
269
269
|
1. Use sf-architect agent to plan trigger handler structure and business logic
|
|
270
|
-
2.
|
|
270
|
+
2. sf-tdd-workflow — write failing test class first (use @TestSetup and test data factory)
|
|
271
271
|
3. Implement AccountTrigger and AccountTriggerHandler
|
|
272
|
-
4.
|
|
272
|
+
4. sf-apex-best-practices to review implementation
|
|
273
273
|
5. Use sf-review-agent agent to verify all tests pass and coverage reaches 75%+
|
|
274
274
|
|
|
275
275
|
Security requirements:
|
|
@@ -279,7 +279,7 @@ Security requirements:
|
|
|
279
279
|
Acceptance criteria:
|
|
280
280
|
- Test coverage 85%+
|
|
281
281
|
- Zero governor limit violations
|
|
282
|
-
- Passes
|
|
282
|
+
- Passes sf-security review
|
|
283
283
|
```
|
|
284
284
|
|
|
285
285
|
### Example 2: Moderate English Prompt
|
|
@@ -309,10 +309,10 @@ Requirements:
|
|
|
309
309
|
|
|
310
310
|
Workflow:
|
|
311
311
|
1. Use sf-architect agent for the endpoint structure, validation logic, and error response envelope
|
|
312
|
-
2.
|
|
312
|
+
2. sf-tdd-workflow — write tests for success, validation failure, permission failure
|
|
313
313
|
3. Implement AccountAPI class following existing REST patterns
|
|
314
|
-
4.
|
|
315
|
-
5.
|
|
314
|
+
4. sf-security — verify CRUD/FLS enforcement
|
|
315
|
+
5. sf-apex-best-practices
|
|
316
316
|
6. Use sf-review-agent agent — run full test suite, confirm no regressions
|
|
317
317
|
|
|
318
318
|
Do not:
|
|
@@ -342,7 +342,7 @@ Before executing, answer these questions in the blueprint:
|
|
|
342
342
|
The blueprint should produce phases like:
|
|
343
343
|
- Phase 1: Audit all existing triggers and document business logic
|
|
344
344
|
- Phase 2: Implement TriggerHandler base class and factory
|
|
345
|
-
- Phase 3: Migrate highest-priority object triggers with
|
|
345
|
+
- Phase 3: Migrate highest-priority object triggers with sf-tdd-workflow gates
|
|
346
346
|
- Phase 4: Migrate remaining triggers
|
|
347
347
|
- Phase N: Remove legacy trigger code, run full regression
|
|
348
348
|
|
|
@@ -24,7 +24,7 @@ Check what's installed in the current project:
|
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
26
|
# Check for SCC installation markers
|
|
27
|
-
ls -la .claude/hooks/ 2>/dev/null
|
|
27
|
+
ls -la .claude/hooks/scripts/ 2>/dev/null
|
|
28
28
|
ls -la .claude/agents/ 2>/dev/null
|
|
29
29
|
ls -la .claude/skills/ 2>/dev/null
|
|
30
30
|
```
|
|
@@ -44,7 +44,7 @@ Rate each category 0-10 using these rubrics:
|
|
|
44
44
|
| 7-8 | All standard profile hooks active |
|
|
45
45
|
| 9-10 | Strict profile enabled, all hooks active including Code Analyzer integration |
|
|
46
46
|
|
|
47
|
-
Check: `
|
|
47
|
+
Check: `npx scc-universal status` to see installed hooks and their profiles.
|
|
48
48
|
Check: `echo $SCC_HOOK_PROFILE` to verify profile level.
|
|
49
49
|
|
|
50
50
|
**Agent Coverage (0-10)**
|
|
@@ -102,7 +102,7 @@ Based on the project state, suggest 3-5 commands to start with:
|
|
|
102
102
|
| Low test coverage | `sf-apex-testing` skill -- analyze gaps |
|
|
103
103
|
| Deployment files present | `sf-deployment` skill -- pre-deployment check |
|
|
104
104
|
| Security review needed | `sf-security` skill -- full security audit |
|
|
105
|
-
| Build errors |
|
|
105
|
+
| Build errors | `sf-build-fix` -- fix build and deployment errors |
|
|
106
106
|
| Any project | `/sf-help` -- browse all available commands and skills |
|
|
107
107
|
|
|
108
108
|
### Step 5 — Verify SCC Installation
|
package/README.md
CHANGED
|
@@ -106,7 +106,8 @@ npx scc-universal uninstall # Remove SCC-managed files
|
|
|
106
106
|
|---|---|---|
|
|
107
107
|
| Agents | `.claude/agents/*.md` | `.cursor/agents/*.md` |
|
|
108
108
|
| Skills | `.claude/skills/*/SKILL.md` | `.cursor/skills/*/SKILL.md` |
|
|
109
|
-
| Hooks | Merged into `.claude/settings.json` | `.cursor/hooks.json` |
|
|
109
|
+
| Hooks (config) | Merged into `.claude/settings.json` | `.cursor/hooks.json` |
|
|
110
|
+
| Hooks (scripts) | `.claude/hooks/scripts/`, `.claude/hooks/lib/` | `.cursor/hooks/scripts/`, `.cursor/hooks/lib/` |
|
|
110
111
|
| MCP config | `.mcp.json` (project root) | `.cursor/mcp.json` |
|
|
111
112
|
|
|
112
113
|
### Install Profiles
|
|
@@ -420,52 +421,21 @@ Control which hooks run via the `SCC_HOOK_PROFILE` environment variable:
|
|
|
420
421
|
|
|
421
422
|
## Tips and Best Practices
|
|
422
423
|
|
|
423
|
-
###
|
|
424
|
+
### Typical Workflows
|
|
424
425
|
|
|
425
|
-
**New Feature
|
|
426
|
+
**New Feature:** Describe what you want to build — sf-architect activates automatically, designs the solution, and delegates to domain agents (sf-apex-agent, sf-lwc-agent, sf-flow-agent) with TDD.
|
|
426
427
|
|
|
427
|
-
|
|
428
|
-
2. `/sf-tdd-workflow` - Write tests first, then implement
|
|
429
|
-
3. `/sf-apex-best-practices` - Review your code
|
|
430
|
-
4. `/sf-deployment` - Deploy to target org
|
|
428
|
+
**Bug Fix:** Describe the error — sf-bugfix-agent activates, diagnoses root cause, applies minimal fix.
|
|
431
429
|
|
|
432
|
-
**Code Review:**
|
|
433
|
-
|
|
434
|
-
1. `/sf-apex-best-practices` - Full review of uncommitted changes
|
|
435
|
-
2. `/sf-security` - Security-focused audit
|
|
436
|
-
3. `/sf-governor-limits` - Check for governor limit issues
|
|
437
|
-
|
|
438
|
-
**Performance Optimization:**
|
|
439
|
-
|
|
440
|
-
1. `/sf-soql-optimization` - Fix expensive queries
|
|
441
|
-
2. `/sf-governor-limits` - Find limit violations
|
|
442
|
-
3. Use the `sf-review-agent` for deep analysis
|
|
443
|
-
|
|
444
|
-
### Context Window Management
|
|
445
|
-
|
|
446
|
-
- Keep MCP servers minimal (SF CLI MCP + 2-3 others)
|
|
447
|
-
- Use specific prompts: "Review AccountTrigger.cls" not "review everything"
|
|
448
|
-
- Use `/compact` when context gets large
|
|
449
|
-
|
|
450
|
-
### Parallel Workflows
|
|
451
|
-
|
|
452
|
-
- Use `/fork` for non-overlapping tasks
|
|
453
|
-
- Use git worktrees for parallel scratch org work:
|
|
454
|
-
|
|
455
|
-
```bash
|
|
456
|
-
git worktree add ../feature-branch feature-branch
|
|
457
|
-
cd ../feature-branch
|
|
458
|
-
sf org create scratch --alias feature-scratch
|
|
459
|
-
```
|
|
430
|
+
**Code Review:** Ask to review before deploy — sf-review-agent runs a full quality gate (security, governor limits, test coverage, deploy readiness).
|
|
460
431
|
|
|
461
432
|
### Key Principles
|
|
462
433
|
|
|
463
434
|
1. **Governor limits are king** — Every agent checks for limit violations
|
|
464
435
|
2. **Test-first approach** — 75% is the SF minimum, aim for 85%+
|
|
465
|
-
3. **
|
|
436
|
+
3. **Be specific** — "Review AccountTrigger.cls" not "review everything"
|
|
466
437
|
4. **Hook profiles matter** — Start with `standard`, move to `strict` for CI
|
|
467
|
-
5. **
|
|
468
|
-
6. **Security baked in** — CRUD/FLS and sharing model from the start
|
|
438
|
+
5. **Security baked in** — CRUD/FLS and sharing model from the start
|
|
469
439
|
|
|
470
440
|
---
|
|
471
441
|
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -117,9 +117,10 @@ npx scc-universal install all
|
|
|
117
117
|
├── Resolve component list for profile
|
|
118
118
|
├── Generate install plan (scripts/dev/install-plan.js)
|
|
119
119
|
├── Execute plan (scripts/cli/install-apply.js)
|
|
120
|
-
│ ├── Copy agents to target
|
|
121
|
-
│ ├── Copy skills to target
|
|
122
|
-
│
|
|
120
|
+
│ ├── Copy agents to target (.claude/agents/)
|
|
121
|
+
│ ├── Copy skills to target (.claude/skills/)
|
|
122
|
+
│ ├── Copy hook scripts + lib (.claude/hooks/scripts/, .claude/hooks/lib/)
|
|
123
|
+
│ └── Merge hook config into .claude/settings.json
|
|
123
124
|
└── Update state store (scripts/lib/state-store.js)
|
|
124
125
|
```
|
|
125
126
|
|
package/docs/authoring-guide.md
CHANGED
|
@@ -360,7 +360,7 @@ Before submitting a pull request that adds new content, verify:
|
|
|
360
360
|
- [ ] `async: true` is set unless the hook must block execution
|
|
361
361
|
- [ ] `timeout` is set to a reasonable value
|
|
362
362
|
- [ ] Test file is created in `tests/hooks/`
|
|
363
|
-
- [ ] Cursor
|
|
363
|
+
- [ ] Cursor hooks are auto-generated by `npm run build` (no manual mirror needed)
|
|
364
364
|
- [ ] `node scripts/ci/validate-hooks.js` passes
|
|
365
365
|
- [ ] `node tests/hooks/my-hook.test.js` passes
|
|
366
366
|
|
package/docs/hook-development.md
CHANGED
|
@@ -385,7 +385,7 @@ if (failCount > 0) process.exit(1);
|
|
|
385
385
|
|
|
386
386
|
### Step 4 -- Update the Cursor Mirror
|
|
387
387
|
|
|
388
|
-
For Cursor IDE parity,
|
|
388
|
+
For Cursor IDE parity, run `npm run build` to regenerate `.cursor/hooks.json`. The adapter layer maps Claude Code lifecycle events to Cursor equivalents automatically.
|
|
389
389
|
|
|
390
390
|
| Claude Code Event | Cursor Equivalent |
|
|
391
391
|
|---|---|
|
|
@@ -221,7 +221,7 @@ Flow: Case Creation from Chat
|
|
|
221
221
|
|
|
222
222
|
## SCC Skills
|
|
223
223
|
|
|
224
|
-
-
|
|
225
|
-
-
|
|
226
|
-
-
|
|
227
|
-
-
|
|
224
|
+
- `sf-agentforce-development` -- scaffold and review Agentforce actions
|
|
225
|
+
- `sf-apex-best-practices` -- review the action class for best practices
|
|
226
|
+
- `sf-tdd-workflow` -- write tests first, then implement the action
|
|
227
|
+
- `sf-governor-limits` -- check governor limit compliance in bulk scenarios
|
|
@@ -319,7 +319,7 @@ jobs:
|
|
|
319
319
|
|
|
320
320
|
## SCC Skills
|
|
321
321
|
|
|
322
|
-
-
|
|
323
|
-
-
|
|
324
|
-
-
|
|
325
|
-
-
|
|
322
|
+
- `sf-deployment` -- validate and deploy metadata to a target org
|
|
323
|
+
- `sf-devops-ci-cd` -- CI/CD pipeline patterns with scratch orgs
|
|
324
|
+
- `sf-build-fix` -- diagnose and fix deployment failures
|
|
325
|
+
- `sf-apex-testing` -- run Apex tests with coverage analysis
|
|
@@ -410,7 +410,7 @@ private class PaymentGatewayService_Test {
|
|
|
410
410
|
|
|
411
411
|
## SCC Skills
|
|
412
412
|
|
|
413
|
-
-
|
|
414
|
-
-
|
|
415
|
-
-
|
|
416
|
-
-
|
|
413
|
+
- `sf-security` -- verify Named Credential usage and no hardcoded secrets
|
|
414
|
+
- `sf-apex-best-practices` -- review callout service code for best practices
|
|
415
|
+
- `sf-tdd-workflow` -- write tests first using mock classes
|
|
416
|
+
- `sf-governor-limits` -- check callout limits in async and batch contexts
|
|
@@ -486,7 +486,7 @@ private class OrderEventPublisher_Test {
|
|
|
486
486
|
|
|
487
487
|
## SCC Skills
|
|
488
488
|
|
|
489
|
-
-
|
|
490
|
-
-
|
|
491
|
-
-
|
|
492
|
-
-
|
|
489
|
+
- `sf-platform-events-cdc` -- review Platform Event and CDC implementations
|
|
490
|
+
- `sf-apex-best-practices` -- review publisher and subscriber Apex code
|
|
491
|
+
- `sf-lwc-development` -- review the empApi subscription component
|
|
492
|
+
- `sf-governor-limits` -- check event publish limits and bulk compliance
|
|
@@ -239,6 +239,6 @@ sf scanner run --target "force-app/" \
|
|
|
239
239
|
|
|
240
240
|
## SCC Skills
|
|
241
241
|
|
|
242
|
-
-
|
|
243
|
-
-
|
|
244
|
-
-
|
|
242
|
+
- `sf-security` -- run a comprehensive security audit on your codebase
|
|
243
|
+
- `sf-apex-best-practices` -- review Apex code including security best practices
|
|
244
|
+
- `sf-governor-limits` -- check for governor limit issues (overlaps with security for SOQL)
|
|
@@ -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
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scc-universal",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
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
|
}
|
|
@@ -96,13 +96,13 @@ Map intent + scope + tech stack (from Phase 0) to specific SCC components.
|
|
|
96
96
|
|
|
97
97
|
| Intent | Invocable Skills | Skills | Agents |
|
|
98
98
|
|--------|----------|--------|--------|
|
|
99
|
-
| New Feature |
|
|
100
|
-
| Bug Fix |
|
|
101
|
-
| Refactor | /refactor-clean,
|
|
102
|
-
| Testing |
|
|
103
|
-
| Review |
|
|
99
|
+
| New Feature | sf-tdd-workflow, sf-apex-best-practices | sf-apex-best-practices, sf-apex-enterprise-patterns | sf-architect, sf-apex-agent, sf-review-agent |
|
|
100
|
+
| Bug Fix | sf-tdd-workflow, sf-build-fix | sf-apex-testing, sf-debugging | sf-bugfix-agent, sf-apex-agent |
|
|
101
|
+
| Refactor | /refactor-clean, sf-apex-best-practices | sf-trigger-frameworks, sf-apex-enterprise-patterns | refactor-cleaner, sf-review-agent |
|
|
102
|
+
| Testing | sf-tdd-workflow, sf-apex-testing, sf-e2e-testing | sf-apex-testing, sf-tdd-workflow | sf-apex-agent |
|
|
103
|
+
| Review | sf-apex-best-practices, sf-lwc-development, sf-security | sf-security | sf-review-agent, sf-review-agent |
|
|
104
104
|
| Documentation | /update-docs | — | doc-updater, deep-researcher |
|
|
105
|
-
| Infrastructure |
|
|
105
|
+
| Infrastructure | sf-deployment | sf-devops-ci-cd, sf-deployment | sf-architect |
|
|
106
106
|
| Design (EPIC) | — | — | sf-architect, sf-architect |
|
|
107
107
|
|
|
108
108
|
#### By Tech Stack
|
|
@@ -164,7 +164,7 @@ For tasks that exceed a single session, split into sequential prompts:
|
|
|
164
164
|
|
|
165
165
|
- Prompt 1: Research + Plan (use search-first skill, then sf-architect agent)
|
|
166
166
|
- Prompt 2-N: Implement one phase per prompt (each ends with sf-review-agent agent)
|
|
167
|
-
- Final Prompt: Integration test +
|
|
167
|
+
- Final Prompt: Integration test + sf-apex-best-practices across all phases
|
|
168
168
|
- Use /save-session and /resume-session to preserve context between sessions
|
|
169
169
|
|
|
170
170
|
---
|
|
@@ -191,7 +191,7 @@ If Phase 0 auto-detected the answer, state it instead of asking.
|
|
|
191
191
|
|
|
192
192
|
| Type | Component | Purpose |
|
|
193
193
|
|------|-----------|---------|
|
|
194
|
-
| Command |
|
|
194
|
+
| Command | sf-tdd-workflow | TDD workflow for Apex |
|
|
195
195
|
| Skill | sf-apex-best-practices | Apex coding standards |
|
|
196
196
|
| Agent | sf-review-agent | Post-implementation review |
|
|
197
197
|
| Model | Sonnet | Recommended for this scope |
|
|
@@ -209,7 +209,7 @@ The prompt must be self-contained and ready to copy-paste. Include:
|
|
|
209
209
|
- Scope boundaries (what NOT to do)
|
|
210
210
|
|
|
211
211
|
For items that reference blueprint, write: "Use the sf-architect agent to..."
|
|
212
|
-
(not
|
|
212
|
+
(not `sf-architect agent`, since sf-architect is an agent, not a command).
|
|
213
213
|
|
|
214
214
|
### Section 4: Optimized Prompt — Quick Version
|
|
215
215
|
|
|
@@ -217,12 +217,12 @@ A compact version for experienced SCC users. Vary by intent type:
|
|
|
217
217
|
|
|
218
218
|
| Intent | Quick Pattern |
|
|
219
219
|
|--------|--------------|
|
|
220
|
-
| New Feature | `Use sf-architect agent for [feature].
|
|
221
|
-
| Bug Fix |
|
|
222
|
-
| Refactor | `/refactor-clean [scope].
|
|
220
|
+
| New Feature | `Use sf-architect agent for [feature]. sf-tdd-workflow to implement. sf-apex-best-practices. Use sf-review-agent agent.` |
|
|
221
|
+
| Bug Fix | `sf-tdd-workflow — write failing test for [bug]. Fix to green. Use sf-review-agent agent.` |
|
|
222
|
+
| Refactor | `/refactor-clean [scope]. sf-apex-best-practices. Use sf-review-agent agent.` |
|
|
223
223
|
| Research | `Use search-first skill for [topic]. Use sf-architect agent based on findings.` |
|
|
224
|
-
| Testing |
|
|
225
|
-
| Review |
|
|
224
|
+
| Testing | `sf-tdd-workflow [class]. sf-e2e-testing for critical flows. sf-apex-testing.` |
|
|
225
|
+
| Review | `sf-apex-best-practices. Then use sf-review-agent agent.` |
|
|
226
226
|
| Docs | `/update-docs. Use deep-researcher agent.` |
|
|
227
227
|
| EPIC | `Use sf-architect agent for "[objective]". Execute phases with sf-review-agent agent gates.` |
|
|
228
228
|
|
|
@@ -270,9 +270,9 @@ Technical requirements:
|
|
|
270
270
|
|
|
271
271
|
Workflow:
|
|
272
272
|
1. Use sf-architect agent to plan trigger handler structure and business logic
|
|
273
|
-
2.
|
|
273
|
+
2. sf-tdd-workflow — write failing test class first (use @TestSetup and test data factory)
|
|
274
274
|
3. Implement AccountTrigger and AccountTriggerHandler
|
|
275
|
-
4.
|
|
275
|
+
4. sf-apex-best-practices to review implementation
|
|
276
276
|
5. Use sf-review-agent agent to verify all tests pass and coverage reaches 75%+
|
|
277
277
|
|
|
278
278
|
Security requirements:
|
|
@@ -282,7 +282,7 @@ Security requirements:
|
|
|
282
282
|
Acceptance criteria:
|
|
283
283
|
- Test coverage 85%+
|
|
284
284
|
- Zero governor limit violations
|
|
285
|
-
- Passes
|
|
285
|
+
- Passes sf-security review
|
|
286
286
|
```
|
|
287
287
|
|
|
288
288
|
### Example 2: Moderate English Prompt
|
|
@@ -312,10 +312,10 @@ Requirements:
|
|
|
312
312
|
|
|
313
313
|
Workflow:
|
|
314
314
|
1. Use sf-architect agent for the endpoint structure, validation logic, and error response envelope
|
|
315
|
-
2.
|
|
315
|
+
2. sf-tdd-workflow — write tests for success, validation failure, permission failure
|
|
316
316
|
3. Implement AccountAPI class following existing REST patterns
|
|
317
|
-
4.
|
|
318
|
-
5.
|
|
317
|
+
4. sf-security — verify CRUD/FLS enforcement
|
|
318
|
+
5. sf-apex-best-practices
|
|
319
319
|
6. Use sf-review-agent agent — run full test suite, confirm no regressions
|
|
320
320
|
|
|
321
321
|
Do not:
|
|
@@ -345,7 +345,7 @@ Before executing, answer these questions in the blueprint:
|
|
|
345
345
|
The blueprint should produce phases like:
|
|
346
346
|
- Phase 1: Audit all existing triggers and document business logic
|
|
347
347
|
- Phase 2: Implement TriggerHandler base class and factory
|
|
348
|
-
- Phase 3: Migrate highest-priority object triggers with
|
|
348
|
+
- Phase 3: Migrate highest-priority object triggers with sf-tdd-workflow gates
|
|
349
349
|
- Phase 4: Migrate remaining triggers
|
|
350
350
|
- Phase N: Remove legacy trigger code, run full regression
|
|
351
351
|
|
|
@@ -27,7 +27,7 @@ Check what's installed in the current project:
|
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
# Check for SCC installation markers
|
|
30
|
-
ls -la .claude/hooks/ 2>/dev/null
|
|
30
|
+
ls -la .claude/hooks/scripts/ 2>/dev/null
|
|
31
31
|
ls -la .claude/agents/ 2>/dev/null
|
|
32
32
|
ls -la .claude/skills/ 2>/dev/null
|
|
33
33
|
```
|
|
@@ -47,7 +47,7 @@ Rate each category 0-10 using these rubrics:
|
|
|
47
47
|
| 7-8 | All standard profile hooks active |
|
|
48
48
|
| 9-10 | Strict profile enabled, all hooks active including Code Analyzer integration |
|
|
49
49
|
|
|
50
|
-
Check: `
|
|
50
|
+
Check: `npx scc-universal status` to see installed hooks and their profiles.
|
|
51
51
|
Check: `echo $SCC_HOOK_PROFILE` to verify profile level.
|
|
52
52
|
|
|
53
53
|
**Agent Coverage (0-10)**
|
|
@@ -105,7 +105,7 @@ Based on the project state, suggest 3-5 commands to start with:
|
|
|
105
105
|
| Low test coverage | `sf-apex-testing` skill -- analyze gaps |
|
|
106
106
|
| Deployment files present | `sf-deployment` skill -- pre-deployment check |
|
|
107
107
|
| Security review needed | `sf-security` skill -- full security audit |
|
|
108
|
-
| Build errors |
|
|
108
|
+
| Build errors | `sf-build-fix` -- fix build and deployment errors |
|
|
109
109
|
| Any project | `/sf-help` -- browse all available commands and skills |
|
|
110
110
|
|
|
111
111
|
### Step 5 — Verify SCC Installation
|
package/.cursor/hooks/adapter.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Cursor-to-Claude Code Hook Adapter
|
|
4
|
-
* Transforms Cursor stdin JSON to Claude Code hook format,
|
|
5
|
-
* then delegates to existing scripts/hooks/*.js
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const { execFileSync } = require('child_process');
|
|
9
|
-
const path = require('path');
|
|
10
|
-
|
|
11
|
-
const MAX_STDIN = 1024 * 1024;
|
|
12
|
-
|
|
13
|
-
function readStdin() {
|
|
14
|
-
return new Promise((resolve) => {
|
|
15
|
-
let data = '';
|
|
16
|
-
process.stdin.setEncoding('utf8');
|
|
17
|
-
process.stdin.on('data', chunk => {
|
|
18
|
-
if (data.length < MAX_STDIN) data += chunk.substring(0, MAX_STDIN - data.length);
|
|
19
|
-
});
|
|
20
|
-
process.stdin.on('end', () => resolve(data));
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function getPluginRoot() {
|
|
25
|
-
return path.resolve(__dirname, '..', '..');
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function transformToClaude(cursorInput, overrides = {}) {
|
|
29
|
-
return {
|
|
30
|
-
tool_input: {
|
|
31
|
-
command: cursorInput.command || cursorInput.args?.command || '',
|
|
32
|
-
file_path: cursorInput.path || cursorInput.file || cursorInput.args?.filePath || '',
|
|
33
|
-
...overrides.tool_input,
|
|
34
|
-
},
|
|
35
|
-
tool_output: {
|
|
36
|
-
output: cursorInput.output || cursorInput.result || '',
|
|
37
|
-
...overrides.tool_output,
|
|
38
|
-
},
|
|
39
|
-
transcript_path: cursorInput.transcript_path || cursorInput.transcriptPath || cursorInput.session?.transcript_path || '',
|
|
40
|
-
_cursor: {
|
|
41
|
-
conversation_id: cursorInput.conversation_id,
|
|
42
|
-
hook_event_name: cursorInput.hook_event_name,
|
|
43
|
-
workspace_roots: cursorInput.workspace_roots,
|
|
44
|
-
model: cursorInput.model,
|
|
45
|
-
},
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function runExistingHook(scriptName, stdinData) {
|
|
50
|
-
const scriptPath = path.join(getPluginRoot(), 'scripts', 'hooks', scriptName);
|
|
51
|
-
try {
|
|
52
|
-
execFileSync('node', [scriptPath], {
|
|
53
|
-
input: typeof stdinData === 'string' ? stdinData : JSON.stringify(stdinData),
|
|
54
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
55
|
-
timeout: 15000,
|
|
56
|
-
cwd: process.cwd(),
|
|
57
|
-
});
|
|
58
|
-
} catch (e) {
|
|
59
|
-
if (e.status === 2) process.exit(2); // Forward blocking exit code
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function hookEnabled(hookId, allowedProfiles = ['standard', 'strict']) {
|
|
64
|
-
const rawProfile = String(process.env.SCC_HOOK_PROFILE || 'standard').toLowerCase();
|
|
65
|
-
const profile = ['minimal', 'standard', 'strict'].includes(rawProfile) ? rawProfile : 'standard';
|
|
66
|
-
|
|
67
|
-
const disabled = new Set(
|
|
68
|
-
String(process.env.SCC_DISABLED_HOOKS || '')
|
|
69
|
-
.split(',')
|
|
70
|
-
.map(v => v.trim().toLowerCase())
|
|
71
|
-
.filter(Boolean)
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
if (disabled.has(String(hookId || '').toLowerCase())) {
|
|
75
|
-
return false;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return allowedProfiles.includes(profile);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
module.exports = { readStdin, getPluginRoot, transformToClaude, runExistingHook, hookEnabled };
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { readStdin, runExistingHook, transformToClaude, hookEnabled } = require('./adapter');
|
|
3
|
-
readStdin().then(raw => {
|
|
4
|
-
try {
|
|
5
|
-
const input = JSON.parse(raw);
|
|
6
|
-
const claudeInput = transformToClaude(input, {
|
|
7
|
-
tool_input: { file_path: input.path || input.file || '' }
|
|
8
|
-
});
|
|
9
|
-
const claudeStr = JSON.stringify(claudeInput);
|
|
10
|
-
|
|
11
|
-
// Run quality-gate, governor-check, console.log warning, and format sequentially
|
|
12
|
-
if (hookEnabled('post:edit:quality-gate', ['standard', 'strict'])) {
|
|
13
|
-
runExistingHook('quality-gate.js', claudeStr);
|
|
14
|
-
}
|
|
15
|
-
if (hookEnabled('post:edit:governor-check', ['standard', 'strict'])) {
|
|
16
|
-
runExistingHook('governor-check.js', claudeStr);
|
|
17
|
-
}
|
|
18
|
-
if (hookEnabled('post:edit:console-warn', ['standard', 'strict'])) {
|
|
19
|
-
runExistingHook('post-edit-console-warn.js', claudeStr);
|
|
20
|
-
}
|
|
21
|
-
if (hookEnabled('post:edit:format', ['strict'])) {
|
|
22
|
-
runExistingHook('post-edit-format.js', claudeStr);
|
|
23
|
-
}
|
|
24
|
-
} catch {}
|
|
25
|
-
process.stdout.write(raw);
|
|
26
|
-
}).catch(() => process.exit(0));
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { readStdin } = require('./adapter');
|
|
3
|
-
readStdin().then(raw => {
|
|
4
|
-
try {
|
|
5
|
-
const input = JSON.parse(raw);
|
|
6
|
-
const server = input.server || input.mcp_server || 'unknown';
|
|
7
|
-
const tool = input.tool || input.mcp_tool || 'unknown';
|
|
8
|
-
const success = input.error ? 'FAILED' : 'OK';
|
|
9
|
-
console.error(`[SCC] MCP result: ${server}/${tool} - ${success}`);
|
|
10
|
-
} catch {}
|
|
11
|
-
process.stdout.write(raw);
|
|
12
|
-
}).catch(() => process.exit(0));
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { readStdin, hookEnabled } = require('./adapter');
|
|
3
|
-
|
|
4
|
-
readStdin().then(raw => {
|
|
5
|
-
try {
|
|
6
|
-
const input = JSON.parse(raw || '{}');
|
|
7
|
-
const cmd = String(input.command || input.args?.command || '');
|
|
8
|
-
const output = String(input.output || input.result || '');
|
|
9
|
-
|
|
10
|
-
if (hookEnabled('post:bash:pr-created', ['standard', 'strict']) && /\bgh\s+pr\s+create\b/.test(cmd)) {
|
|
11
|
-
const m = output.match(/https:\/\/github\.com\/[^/]+\/[^/]+\/pull\/\d+/);
|
|
12
|
-
if (m) {
|
|
13
|
-
console.error('[SCC] PR created: ' + m[0]);
|
|
14
|
-
const repo = m[0].replace(/https:\/\/github\.com\/([^/]+\/[^/]+)\/pull\/\d+/, '$1');
|
|
15
|
-
const pr = m[0].replace(/.+\/pull\/(\d+)/, '$1');
|
|
16
|
-
console.error('[SCC] To review: gh pr review ' + pr + ' --repo ' + repo);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (hookEnabled('post:bash:build-complete', ['standard', 'strict'])) {
|
|
21
|
-
if (/(sf\s+project\s+deploy|sf\s+deploy|sfdx\s+force:source:deploy|npm run build|pnpm build|yarn build)/.test(cmd)) {
|
|
22
|
-
console.error('[SCC] Build/deploy completed — review results above');
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
} catch {
|
|
26
|
-
// noop
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
process.stdout.write(raw);
|
|
30
|
-
}).catch(() => process.exit(0));
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { readStdin, runExistingHook, transformToClaude } = require('./adapter');
|
|
3
|
-
readStdin().then(raw => {
|
|
4
|
-
try {
|
|
5
|
-
const input = JSON.parse(raw);
|
|
6
|
-
const claudeInput = transformToClaude(input, {
|
|
7
|
-
tool_input: { file_path: input.path || input.file || '' }
|
|
8
|
-
});
|
|
9
|
-
runExistingHook('post-edit-format.js', JSON.stringify(claudeInput));
|
|
10
|
-
} catch {}
|
|
11
|
-
process.stdout.write(raw);
|
|
12
|
-
}).catch(() => process.exit(0));
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { readStdin } = require('./adapter');
|
|
3
|
-
readStdin().then(raw => {
|
|
4
|
-
try {
|
|
5
|
-
const input = JSON.parse(raw);
|
|
6
|
-
const server = input.server || input.mcp_server || 'unknown';
|
|
7
|
-
const tool = input.tool || input.mcp_tool || 'unknown';
|
|
8
|
-
console.error(`[SCC] MCP invocation: ${server}/${tool}`);
|
|
9
|
-
} catch {}
|
|
10
|
-
process.stdout.write(raw);
|
|
11
|
-
}).catch(() => process.exit(0));
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { readStdin } = require('./adapter');
|
|
3
|
-
readStdin().then(raw => {
|
|
4
|
-
try {
|
|
5
|
-
const input = JSON.parse(raw);
|
|
6
|
-
const filePath = input.path || input.file || '';
|
|
7
|
-
if (/\.(env|key|pem)$|\.env\.|credentials|secret/i.test(filePath)) {
|
|
8
|
-
console.error('[SCC] WARNING: Reading sensitive file: ' + filePath);
|
|
9
|
-
console.error('[SCC] Ensure this data is not exposed in outputs');
|
|
10
|
-
}
|
|
11
|
-
} catch {}
|
|
12
|
-
process.stdout.write(raw);
|
|
13
|
-
}).catch(() => process.exit(0));
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { readStdin, runExistingHook, transformToClaude, hookEnabled } = require('./adapter');
|
|
3
|
-
|
|
4
|
-
readStdin()
|
|
5
|
-
.then(raw => {
|
|
6
|
-
try {
|
|
7
|
-
const input = JSON.parse(raw || '{}');
|
|
8
|
-
const cmd = String(input.command || input.args?.command || '');
|
|
9
|
-
|
|
10
|
-
// SFDX validation
|
|
11
|
-
if (hookEnabled('pre:bash:sfdx-validate', ['standard', 'strict']) && (/\bsf\s/.test(cmd) || /\bsfdx\s/.test(cmd))) {
|
|
12
|
-
const claudeInput = transformToClaude(input, {
|
|
13
|
-
tool_input: { command: cmd }
|
|
14
|
-
});
|
|
15
|
-
claudeInput.tool_name = 'Bash';
|
|
16
|
-
runExistingHook('sfdx-validate.js', JSON.stringify(claudeInput));
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Git push reminder
|
|
20
|
-
if (hookEnabled('pre:bash:git-push-reminder', ['standard', 'strict']) && /\bgit\s+push\b/.test(cmd)) {
|
|
21
|
-
console.error('[SCC] Review changes before push: git diff origin/main...HEAD');
|
|
22
|
-
}
|
|
23
|
-
} catch {
|
|
24
|
-
// noop
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
process.stdout.write(raw);
|
|
28
|
-
})
|
|
29
|
-
.catch(() => process.exit(0));
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { readStdin } = require('./adapter');
|
|
3
|
-
readStdin().then(raw => {
|
|
4
|
-
try {
|
|
5
|
-
const input = JSON.parse(raw);
|
|
6
|
-
const prompt = input.prompt || input.content || input.message || '';
|
|
7
|
-
const secretPatterns = [
|
|
8
|
-
/sk-[a-zA-Z0-9]{20,}/, // OpenAI API keys
|
|
9
|
-
/ghp_[a-zA-Z0-9]{36,}/, // GitHub personal access tokens
|
|
10
|
-
/AKIA[A-Z0-9]{16}/, // AWS access keys
|
|
11
|
-
/xox[bpsa]-[a-zA-Z0-9-]+/, // Slack tokens
|
|
12
|
-
/-----BEGIN (RSA |EC )?PRIVATE KEY-----/, // Private keys
|
|
13
|
-
];
|
|
14
|
-
for (const pattern of secretPatterns) {
|
|
15
|
-
if (pattern.test(prompt)) {
|
|
16
|
-
console.error('[SCC] WARNING: Potential secret detected in prompt!');
|
|
17
|
-
console.error('[SCC] Remove secrets before submitting. Use environment variables instead.');
|
|
18
|
-
break;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
} catch {}
|
|
22
|
-
process.stdout.write(raw);
|
|
23
|
-
}).catch(() => process.exit(0));
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { readStdin, runExistingHook, transformToClaude } = require('./adapter');
|
|
3
|
-
readStdin().then(raw => {
|
|
4
|
-
const claudeInput = JSON.parse(raw || '{}');
|
|
5
|
-
runExistingHook('pre-compact.js', transformToClaude(claudeInput));
|
|
6
|
-
process.stdout.write(raw);
|
|
7
|
-
}).catch(() => process.exit(0));
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { readStdin, runExistingHook, transformToClaude, hookEnabled } = require('./adapter');
|
|
3
|
-
readStdin().then(raw => {
|
|
4
|
-
const input = JSON.parse(raw || '{}');
|
|
5
|
-
const claudeInput = transformToClaude(input);
|
|
6
|
-
if (hookEnabled('session:end:marker', ['minimal', 'standard', 'strict'])) {
|
|
7
|
-
runExistingHook('session-end-marker.js', claudeInput);
|
|
8
|
-
}
|
|
9
|
-
process.stdout.write(raw);
|
|
10
|
-
}).catch(() => process.exit(0));
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { readStdin, runExistingHook, transformToClaude, hookEnabled } = require('./adapter');
|
|
3
|
-
readStdin().then(raw => {
|
|
4
|
-
const input = JSON.parse(raw || '{}');
|
|
5
|
-
const claudeInput = transformToClaude(input);
|
|
6
|
-
if (hookEnabled('session:start', ['minimal', 'standard', 'strict'])) {
|
|
7
|
-
runExistingHook('session-start.js', claudeInput);
|
|
8
|
-
}
|
|
9
|
-
process.stdout.write(raw);
|
|
10
|
-
}).catch(() => process.exit(0));
|
package/.cursor/hooks/stop.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { readStdin, runExistingHook, transformToClaude, hookEnabled } = require('./adapter');
|
|
3
|
-
readStdin().then(raw => {
|
|
4
|
-
const input = JSON.parse(raw || '{}');
|
|
5
|
-
const claudeInput = transformToClaude(input);
|
|
6
|
-
|
|
7
|
-
if (hookEnabled('stop:check-console-log', ['standard', 'strict'])) {
|
|
8
|
-
runExistingHook('check-console-log.js', claudeInput);
|
|
9
|
-
}
|
|
10
|
-
if (hookEnabled('stop:session-end', ['minimal', 'standard', 'strict'])) {
|
|
11
|
-
runExistingHook('session-end.js', claudeInput);
|
|
12
|
-
}
|
|
13
|
-
if (hookEnabled('stop:cost-tracker', ['minimal', 'standard', 'strict'])) {
|
|
14
|
-
runExistingHook('cost-tracker.js', claudeInput);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
process.stdout.write(raw);
|
|
18
|
-
}).catch(() => process.exit(0));
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { readStdin } = require('./adapter');
|
|
3
|
-
readStdin().then(raw => {
|
|
4
|
-
try {
|
|
5
|
-
const input = JSON.parse(raw);
|
|
6
|
-
const agent = input.agent_name || input.agent || 'unknown';
|
|
7
|
-
console.error(`[SCC] Agent spawned: ${agent}`);
|
|
8
|
-
} catch {}
|
|
9
|
-
process.stdout.write(raw);
|
|
10
|
-
}).catch(() => process.exit(0));
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { readStdin } = require('./adapter');
|
|
3
|
-
readStdin().then(raw => {
|
|
4
|
-
try {
|
|
5
|
-
const input = JSON.parse(raw);
|
|
6
|
-
const agent = input.agent_name || input.agent || 'unknown';
|
|
7
|
-
console.error(`[SCC] Agent completed: ${agent}`);
|
|
8
|
-
} catch {}
|
|
9
|
-
process.stdout.write(raw);
|
|
10
|
-
}).catch(() => process.exit(0));
|