scc-universal 1.1.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 (271) hide show
  1. package/.claude-plugin/plugin.json +44 -0
  2. package/.cursor/agents/deep-researcher.md +142 -0
  3. package/.cursor/agents/doc-updater.md +219 -0
  4. package/.cursor/agents/eval-runner.md +335 -0
  5. package/.cursor/agents/learning-engine.md +210 -0
  6. package/.cursor/agents/loop-operator.md +245 -0
  7. package/.cursor/agents/refactor-cleaner.md +119 -0
  8. package/.cursor/agents/sf-admin-agent.md +127 -0
  9. package/.cursor/agents/sf-agentforce-agent.md +126 -0
  10. package/.cursor/agents/sf-apex-agent.md +117 -0
  11. package/.cursor/agents/sf-architect.md +426 -0
  12. package/.cursor/agents/sf-aura-reviewer.md +369 -0
  13. package/.cursor/agents/sf-bugfix-agent.md +101 -0
  14. package/.cursor/agents/sf-flow-agent.md +155 -0
  15. package/.cursor/agents/sf-integration-agent.md +141 -0
  16. package/.cursor/agents/sf-lwc-agent.md +123 -0
  17. package/.cursor/agents/sf-review-agent.md +357 -0
  18. package/.cursor/agents/sf-visualforce-reviewer.md +465 -0
  19. package/.cursor/hooks/adapter.js +81 -0
  20. package/.cursor/hooks/after-file-edit.js +26 -0
  21. package/.cursor/hooks/after-mcp-execution.js +12 -0
  22. package/.cursor/hooks/after-shell-execution.js +30 -0
  23. package/.cursor/hooks/after-tab-file-edit.js +12 -0
  24. package/.cursor/hooks/before-mcp-execution.js +11 -0
  25. package/.cursor/hooks/before-read-file.js +13 -0
  26. package/.cursor/hooks/before-shell-execution.js +29 -0
  27. package/.cursor/hooks/before-submit-prompt.js +23 -0
  28. package/.cursor/hooks/pre-compact.js +7 -0
  29. package/.cursor/hooks/session-end.js +10 -0
  30. package/.cursor/hooks/session-start.js +10 -0
  31. package/.cursor/hooks/stop.js +18 -0
  32. package/.cursor/hooks/subagent-start.js +10 -0
  33. package/.cursor/hooks/subagent-stop.js +10 -0
  34. package/.cursor/hooks.json +107 -0
  35. package/.cursor/skills/aside/SKILL.md +115 -0
  36. package/.cursor/skills/checkpoint/SKILL.md +50 -0
  37. package/.cursor/skills/configure-scc/SKILL.md +160 -0
  38. package/.cursor/skills/continuous-agent-loop/SKILL.md +260 -0
  39. package/.cursor/skills/mcp-server-patterns/SKILL.md +142 -0
  40. package/.cursor/skills/model-route/SKILL.md +81 -0
  41. package/.cursor/skills/prompt-optimizer/SKILL.md +366 -0
  42. package/.cursor/skills/refactor-clean/SKILL.md +133 -0
  43. package/.cursor/skills/resume-session/SKILL.md +111 -0
  44. package/.cursor/skills/save-session/SKILL.md +183 -0
  45. package/.cursor/skills/search-first/SKILL.md +140 -0
  46. package/.cursor/skills/security-scan/SKILL.md +142 -0
  47. package/.cursor/skills/sessions/SKILL.md +124 -0
  48. package/.cursor/skills/sf-agentforce-development/SKILL.md +449 -0
  49. package/.cursor/skills/sf-apex-async-patterns/SKILL.md +324 -0
  50. package/.cursor/skills/sf-apex-best-practices/SKILL.md +421 -0
  51. package/.cursor/skills/sf-apex-constraints/SKILL.md +79 -0
  52. package/.cursor/skills/sf-apex-cursor/SKILL.md +336 -0
  53. package/.cursor/skills/sf-apex-enterprise-patterns/SKILL.md +344 -0
  54. package/.cursor/skills/sf-apex-testing/SKILL.md +407 -0
  55. package/.cursor/skills/sf-api-design/SKILL.md +237 -0
  56. package/.cursor/skills/sf-approval-processes/SKILL.md +312 -0
  57. package/.cursor/skills/sf-aura-development/SKILL.md +260 -0
  58. package/.cursor/skills/sf-build-fix/SKILL.md +120 -0
  59. package/.cursor/skills/sf-data-modeling/SKILL.md +274 -0
  60. package/.cursor/skills/sf-debugging/SKILL.md +362 -0
  61. package/.cursor/skills/sf-deployment/SKILL.md +291 -0
  62. package/.cursor/skills/sf-deployment-constraints/SKILL.md +153 -0
  63. package/.cursor/skills/sf-devops-ci-cd/SKILL.md +322 -0
  64. package/.cursor/skills/sf-docs-lookup/SKILL.md +100 -0
  65. package/.cursor/skills/sf-e2e-testing/SKILL.md +321 -0
  66. package/.cursor/skills/sf-experience-cloud/SKILL.md +248 -0
  67. package/.cursor/skills/sf-flow-development/SKILL.md +376 -0
  68. package/.cursor/skills/sf-governor-limits/SKILL.md +319 -0
  69. package/.cursor/skills/sf-harness-audit/SKILL.md +139 -0
  70. package/.cursor/skills/sf-help/SKILL.md +156 -0
  71. package/.cursor/skills/sf-integration/SKILL.md +479 -0
  72. package/.cursor/skills/sf-lwc-constraints/SKILL.md +128 -0
  73. package/.cursor/skills/sf-lwc-development/SKILL.md +302 -0
  74. package/.cursor/skills/sf-lwc-testing/SKILL.md +387 -0
  75. package/.cursor/skills/sf-metadata-management/SKILL.md +285 -0
  76. package/.cursor/skills/sf-platform-events-cdc/SKILL.md +372 -0
  77. package/.cursor/skills/sf-quickstart/SKILL.md +170 -0
  78. package/.cursor/skills/sf-security/SKILL.md +330 -0
  79. package/.cursor/skills/sf-security-constraints/SKILL.md +125 -0
  80. package/.cursor/skills/sf-soql-constraints/SKILL.md +129 -0
  81. package/.cursor/skills/sf-soql-optimization/SKILL.md +353 -0
  82. package/.cursor/skills/sf-tdd-workflow/SKILL.md +332 -0
  83. package/.cursor/skills/sf-testing-constraints/SKILL.md +198 -0
  84. package/.cursor/skills/sf-trigger-constraints/SKILL.md +88 -0
  85. package/.cursor/skills/sf-trigger-frameworks/SKILL.md +343 -0
  86. package/.cursor/skills/sf-visualforce-development/SKILL.md +259 -0
  87. package/.cursor/skills/strategic-compact/SKILL.md +205 -0
  88. package/.cursor/skills/update-docs/SKILL.md +162 -0
  89. package/.cursor/skills/update-platform-docs/SKILL.md +86 -0
  90. package/.cursor-plugin/plugin.json +26 -0
  91. package/LICENSE +21 -0
  92. package/README.md +522 -0
  93. package/agents/deep-researcher.md +145 -0
  94. package/agents/doc-updater.md +222 -0
  95. package/agents/eval-runner.md +340 -0
  96. package/agents/learning-engine.md +211 -0
  97. package/agents/loop-operator.md +247 -0
  98. package/agents/refactor-cleaner.md +122 -0
  99. package/agents/sf-admin-agent.md +131 -0
  100. package/agents/sf-agentforce-agent.md +132 -0
  101. package/agents/sf-apex-agent.md +124 -0
  102. package/agents/sf-architect.md +435 -0
  103. package/agents/sf-aura-reviewer.md +372 -0
  104. package/agents/sf-bugfix-agent.md +105 -0
  105. package/agents/sf-flow-agent.md +159 -0
  106. package/agents/sf-integration-agent.md +146 -0
  107. package/agents/sf-lwc-agent.md +127 -0
  108. package/agents/sf-review-agent.md +366 -0
  109. package/agents/sf-visualforce-reviewer.md +468 -0
  110. package/assets/logo.svg +18 -0
  111. package/docs/ARCHITECTURE.md +133 -0
  112. package/docs/authoring-guide.md +373 -0
  113. package/docs/hook-development.md +578 -0
  114. package/docs/token-optimization.md +139 -0
  115. package/docs/workflow-examples.md +645 -0
  116. package/examples/agentforce-action/README.md +227 -0
  117. package/examples/apex-trigger-handler/README.md +114 -0
  118. package/examples/devops-pipeline/README.md +325 -0
  119. package/examples/flow-automation/README.md +188 -0
  120. package/examples/integration-pattern/README.md +416 -0
  121. package/examples/lwc-component/README.md +180 -0
  122. package/examples/platform-events/README.md +492 -0
  123. package/examples/scratch-org-setup/README.md +138 -0
  124. package/examples/security-audit/README.md +244 -0
  125. package/examples/visualforce-migration/README.md +314 -0
  126. package/hooks/hooks.json +338 -0
  127. package/hooks/memory-persistence/README.md +73 -0
  128. package/manifests/install-modules.json +217 -0
  129. package/manifests/install-profiles.json +17 -0
  130. package/mcp-configs/mcp-servers.json +19 -0
  131. package/package.json +89 -0
  132. package/schemas/hooks.schema.json +123 -0
  133. package/schemas/install-modules.schema.json +76 -0
  134. package/schemas/install-profiles.schema.json +28 -0
  135. package/schemas/install-state.schema.json +73 -0
  136. package/schemas/package-manager.schema.json +18 -0
  137. package/schemas/plugin.schema.json +112 -0
  138. package/schemas/scc-install-config.schema.json +29 -0
  139. package/schemas/state-store.schema.json +111 -0
  140. package/scripts/cli/install-apply.js +170 -0
  141. package/scripts/cli/uninstall.js +193 -0
  142. package/scripts/hooks/check-console-log.js +101 -0
  143. package/scripts/hooks/check-hook-enabled.js +17 -0
  144. package/scripts/hooks/check-platform-docs-age.js +48 -0
  145. package/scripts/hooks/cost-tracker.js +78 -0
  146. package/scripts/hooks/doc-file-warning.js +63 -0
  147. package/scripts/hooks/evaluate-session.js +98 -0
  148. package/scripts/hooks/governor-check.js +220 -0
  149. package/scripts/hooks/learning-observe.sh +206 -0
  150. package/scripts/hooks/mcp-health-check.js +588 -0
  151. package/scripts/hooks/post-bash-build-complete.js +34 -0
  152. package/scripts/hooks/post-bash-pr-created.js +43 -0
  153. package/scripts/hooks/post-edit-console-warn.js +61 -0
  154. package/scripts/hooks/post-edit-format.js +79 -0
  155. package/scripts/hooks/post-edit-typecheck.js +98 -0
  156. package/scripts/hooks/post-write.js +168 -0
  157. package/scripts/hooks/pre-bash-git-push-reminder.js +35 -0
  158. package/scripts/hooks/pre-bash-tmux-reminder.js +47 -0
  159. package/scripts/hooks/pre-compact.js +51 -0
  160. package/scripts/hooks/pre-tool-use.js +163 -0
  161. package/scripts/hooks/pre-write-doc-warn.js +9 -0
  162. package/scripts/hooks/quality-gate.js +251 -0
  163. package/scripts/hooks/run-with-flags-shell.sh +32 -0
  164. package/scripts/hooks/run-with-flags.js +135 -0
  165. package/scripts/hooks/session-end-marker.js +29 -0
  166. package/scripts/hooks/session-end.js +311 -0
  167. package/scripts/hooks/session-start.js +202 -0
  168. package/scripts/hooks/sfdx-scanner-check.js +142 -0
  169. package/scripts/hooks/sfdx-validate.js +119 -0
  170. package/scripts/hooks/stop-hook.js +170 -0
  171. package/scripts/hooks/suggest-compact.js +67 -0
  172. package/scripts/lib/agent-adapter.js +82 -0
  173. package/scripts/lib/apex-analysis.js +194 -0
  174. package/scripts/lib/hook-flags.js +74 -0
  175. package/scripts/lib/install-config.js +73 -0
  176. package/scripts/lib/install-executor.js +363 -0
  177. package/scripts/lib/install-state.js +121 -0
  178. package/scripts/lib/orchestration-session.js +299 -0
  179. package/scripts/lib/package-manager.js +124 -0
  180. package/scripts/lib/project-detect.js +228 -0
  181. package/scripts/lib/schema-validator.js +190 -0
  182. package/scripts/lib/skill-adapter.js +100 -0
  183. package/scripts/lib/state-store.js +376 -0
  184. package/scripts/lib/tmux-worktree-orchestrator.js +598 -0
  185. package/scripts/lib/utils.js +313 -0
  186. package/scripts/scc.js +164 -0
  187. package/skills/_reference/AGENTFORCE_PATTERNS.md +112 -0
  188. package/skills/_reference/APEX_CURSOR.md +159 -0
  189. package/skills/_reference/API_VERSIONS.md +78 -0
  190. package/skills/_reference/APPROVAL_PROCESSES.md +105 -0
  191. package/skills/_reference/ASYNC_PATTERNS.md +163 -0
  192. package/skills/_reference/AURA_COMPONENTS.md +146 -0
  193. package/skills/_reference/DATA_MIGRATION_PATTERNS.md +151 -0
  194. package/skills/_reference/DATA_MODELING.md +124 -0
  195. package/skills/_reference/DEBUGGING_TOOLS.md +140 -0
  196. package/skills/_reference/DEPLOYMENT_CHECKLIST.md +87 -0
  197. package/skills/_reference/DEPRECATIONS.md +79 -0
  198. package/skills/_reference/DOCKER_CI_PATTERNS.md +138 -0
  199. package/skills/_reference/ENTERPRISE_PATTERNS.md +122 -0
  200. package/skills/_reference/EXPERIENCE_CLOUD.md +143 -0
  201. package/skills/_reference/FLOW_PATTERNS.md +113 -0
  202. package/skills/_reference/GOVERNOR_LIMITS.md +77 -0
  203. package/skills/_reference/INTEGRATION_PATTERNS.md +105 -0
  204. package/skills/_reference/LWC_PATTERNS.md +79 -0
  205. package/skills/_reference/METADATA_TYPES.md +115 -0
  206. package/skills/_reference/NAMING_CONVENTIONS.md +84 -0
  207. package/skills/_reference/PACKAGE_DEVELOPMENT.md +150 -0
  208. package/skills/_reference/PLATFORM_EVENTS.md +121 -0
  209. package/skills/_reference/REPORTING_API.md +143 -0
  210. package/skills/_reference/SCRATCH_ORG_PATTERNS.md +126 -0
  211. package/skills/_reference/SECURITY_PATTERNS.md +127 -0
  212. package/skills/_reference/SHARING_MODEL.md +120 -0
  213. package/skills/_reference/SOQL_PATTERNS.md +119 -0
  214. package/skills/_reference/TESTING_STANDARDS.md +96 -0
  215. package/skills/_reference/TRIGGER_PATTERNS.md +114 -0
  216. package/skills/_reference/VISUALFORCE_PATTERNS.md +121 -0
  217. package/skills/aside/SKILL.md +118 -0
  218. package/skills/checkpoint/SKILL.md +53 -0
  219. package/skills/configure-scc/SKILL.md +163 -0
  220. package/skills/continuous-agent-loop/SKILL.md +264 -0
  221. package/skills/mcp-server-patterns/SKILL.md +146 -0
  222. package/skills/model-route/SKILL.md +84 -0
  223. package/skills/prompt-optimizer/SKILL.md +369 -0
  224. package/skills/refactor-clean/SKILL.md +136 -0
  225. package/skills/resume-session/SKILL.md +114 -0
  226. package/skills/save-session/SKILL.md +186 -0
  227. package/skills/search-first/SKILL.md +144 -0
  228. package/skills/security-scan/SKILL.md +146 -0
  229. package/skills/sessions/SKILL.md +127 -0
  230. package/skills/sf-agentforce-development/SKILL.md +450 -0
  231. package/skills/sf-apex-async-patterns/SKILL.md +326 -0
  232. package/skills/sf-apex-best-practices/SKILL.md +425 -0
  233. package/skills/sf-apex-constraints/SKILL.md +81 -0
  234. package/skills/sf-apex-cursor/SKILL.md +338 -0
  235. package/skills/sf-apex-enterprise-patterns/SKILL.md +348 -0
  236. package/skills/sf-apex-testing/SKILL.md +409 -0
  237. package/skills/sf-api-design/SKILL.md +238 -0
  238. package/skills/sf-approval-processes/SKILL.md +315 -0
  239. package/skills/sf-aura-development/SKILL.md +263 -0
  240. package/skills/sf-build-fix/SKILL.md +121 -0
  241. package/skills/sf-data-modeling/SKILL.md +278 -0
  242. package/skills/sf-debugging/SKILL.md +363 -0
  243. package/skills/sf-deployment/SKILL.md +295 -0
  244. package/skills/sf-deployment-constraints/SKILL.md +155 -0
  245. package/skills/sf-devops-ci-cd/SKILL.md +325 -0
  246. package/skills/sf-docs-lookup/SKILL.md +103 -0
  247. package/skills/sf-e2e-testing/SKILL.md +324 -0
  248. package/skills/sf-experience-cloud/SKILL.md +249 -0
  249. package/skills/sf-flow-development/SKILL.md +377 -0
  250. package/skills/sf-governor-limits/SKILL.md +323 -0
  251. package/skills/sf-harness-audit/SKILL.md +142 -0
  252. package/skills/sf-help/SKILL.md +159 -0
  253. package/skills/sf-integration/SKILL.md +483 -0
  254. package/skills/sf-lwc-constraints/SKILL.md +130 -0
  255. package/skills/sf-lwc-development/SKILL.md +303 -0
  256. package/skills/sf-lwc-testing/SKILL.md +388 -0
  257. package/skills/sf-metadata-management/SKILL.md +288 -0
  258. package/skills/sf-platform-events-cdc/SKILL.md +375 -0
  259. package/skills/sf-quickstart/SKILL.md +173 -0
  260. package/skills/sf-security/SKILL.md +334 -0
  261. package/skills/sf-security-constraints/SKILL.md +127 -0
  262. package/skills/sf-soql-constraints/SKILL.md +131 -0
  263. package/skills/sf-soql-optimization/SKILL.md +354 -0
  264. package/skills/sf-tdd-workflow/SKILL.md +336 -0
  265. package/skills/sf-testing-constraints/SKILL.md +200 -0
  266. package/skills/sf-trigger-constraints/SKILL.md +90 -0
  267. package/skills/sf-trigger-frameworks/SKILL.md +347 -0
  268. package/skills/sf-visualforce-development/SKILL.md +260 -0
  269. package/skills/strategic-compact/SKILL.md +208 -0
  270. package/skills/update-docs/SKILL.md +165 -0
  271. package/skills/update-platform-docs/SKILL.md +90 -0
@@ -0,0 +1,299 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { spawnSync } = require('child_process');
6
+
7
+ function stripCodeTicks(value) {
8
+ if (typeof value !== 'string') {
9
+ return value;
10
+ }
11
+
12
+ const trimmed = value.trim();
13
+ if (trimmed.startsWith('`') && trimmed.endsWith('`') && trimmed.length >= 2) {
14
+ return trimmed.slice(1, -1);
15
+ }
16
+
17
+ return trimmed;
18
+ }
19
+
20
+ function parseSection(content, heading) {
21
+ if (typeof content !== 'string' || content.length === 0) {
22
+ return '';
23
+ }
24
+
25
+ const lines = content.split('\n');
26
+ const headingLines = new Set([`## ${heading}`, `**${heading}**`]);
27
+ const startIndex = lines.findIndex(line => headingLines.has(line.trim()));
28
+
29
+ if (startIndex === -1) {
30
+ return '';
31
+ }
32
+
33
+ const collected = [];
34
+ for (let index = startIndex + 1; index < lines.length; index += 1) {
35
+ const line = lines[index];
36
+ const trimmed = line.trim();
37
+ if (trimmed.startsWith('## ') || (/^\*\*.+\*\*$/.test(trimmed) && !headingLines.has(trimmed))) {
38
+ break;
39
+ }
40
+ collected.push(line);
41
+ }
42
+
43
+ return collected.join('\n').trim();
44
+ }
45
+
46
+ function parseBullets(section) {
47
+ if (!section) {
48
+ return [];
49
+ }
50
+
51
+ return section
52
+ .split('\n')
53
+ .map(line => line.trim())
54
+ .filter(line => line.startsWith('- '))
55
+ .map(line => stripCodeTicks(line.replace(/^- /, '').trim()));
56
+ }
57
+
58
+ function parseWorkerStatus(content) {
59
+ const status = {
60
+ state: null,
61
+ updated: null,
62
+ branch: null,
63
+ worktree: null,
64
+ taskFile: null,
65
+ handoffFile: null
66
+ };
67
+
68
+ if (typeof content !== 'string' || content.length === 0) {
69
+ return status;
70
+ }
71
+
72
+ for (const line of content.split('\n')) {
73
+ const match = line.match(/^- ([A-Za-z ]+):\s*(.+)$/);
74
+ if (!match) {
75
+ continue;
76
+ }
77
+
78
+ const key = match[1].trim().toLowerCase().replace(/\s+/g, '');
79
+ const value = stripCodeTicks(match[2]);
80
+
81
+ if (key === 'state') status.state = value;
82
+ if (key === 'updated') status.updated = value;
83
+ if (key === 'branch') status.branch = value;
84
+ if (key === 'worktree') status.worktree = value;
85
+ if (key === 'taskfile') status.taskFile = value;
86
+ if (key === 'handofffile') status.handoffFile = value;
87
+ }
88
+
89
+ return status;
90
+ }
91
+
92
+ function parseWorkerTask(content) {
93
+ return {
94
+ objective: parseSection(content, 'Objective'),
95
+ seedPaths: parseBullets(parseSection(content, 'Seeded Local Overlays'))
96
+ };
97
+ }
98
+
99
+ function parseWorkerHandoff(content) {
100
+ return {
101
+ summary: parseBullets(parseSection(content, 'Summary')),
102
+ validation: parseBullets(parseSection(content, 'Validation')),
103
+ remainingRisks: parseBullets(parseSection(content, 'Remaining Risks'))
104
+ };
105
+ }
106
+
107
+ function readTextIfExists(filePath) {
108
+ if (!filePath || !fs.existsSync(filePath)) {
109
+ return '';
110
+ }
111
+
112
+ return fs.readFileSync(filePath, 'utf8');
113
+ }
114
+
115
+ function listWorkerDirectories(coordinationDir) {
116
+ if (!coordinationDir || !fs.existsSync(coordinationDir)) {
117
+ return [];
118
+ }
119
+
120
+ return fs.readdirSync(coordinationDir, { withFileTypes: true })
121
+ .filter(entry => entry.isDirectory())
122
+ .filter(entry => {
123
+ const workerDir = path.join(coordinationDir, entry.name);
124
+ return ['status.md', 'task.md', 'handoff.md']
125
+ .some(filename => fs.existsSync(path.join(workerDir, filename)));
126
+ })
127
+ .map(entry => entry.name)
128
+ .sort();
129
+ }
130
+
131
+ function loadWorkerSnapshots(coordinationDir) {
132
+ return listWorkerDirectories(coordinationDir).map(workerSlug => {
133
+ const workerDir = path.join(coordinationDir, workerSlug);
134
+ const statusPath = path.join(workerDir, 'status.md');
135
+ const taskPath = path.join(workerDir, 'task.md');
136
+ const handoffPath = path.join(workerDir, 'handoff.md');
137
+
138
+ const status = parseWorkerStatus(readTextIfExists(statusPath));
139
+ const task = parseWorkerTask(readTextIfExists(taskPath));
140
+ const handoff = parseWorkerHandoff(readTextIfExists(handoffPath));
141
+
142
+ return {
143
+ workerSlug,
144
+ workerDir,
145
+ status,
146
+ task,
147
+ handoff,
148
+ files: {
149
+ status: statusPath,
150
+ task: taskPath,
151
+ handoff: handoffPath
152
+ }
153
+ };
154
+ });
155
+ }
156
+
157
+ function listTmuxPanes(sessionName, options = {}) {
158
+ const { spawnSyncImpl = spawnSync } = options;
159
+ const format = [
160
+ '#{pane_id}',
161
+ '#{window_index}',
162
+ '#{pane_index}',
163
+ '#{pane_title}',
164
+ '#{pane_current_command}',
165
+ '#{pane_current_path}',
166
+ '#{pane_active}',
167
+ '#{pane_dead}',
168
+ '#{pane_pid}'
169
+ ].join('\t');
170
+
171
+ const result = spawnSyncImpl('tmux', ['list-panes', '-t', sessionName, '-F', format], {
172
+ encoding: 'utf8',
173
+ stdio: ['ignore', 'pipe', 'pipe']
174
+ });
175
+
176
+ if (result.error) {
177
+ if (result.error.code === 'ENOENT') {
178
+ return [];
179
+ }
180
+ throw result.error;
181
+ }
182
+
183
+ if (result.status !== 0) {
184
+ return [];
185
+ }
186
+
187
+ return (result.stdout || '')
188
+ .split('\n')
189
+ .map(line => line.trim())
190
+ .filter(Boolean)
191
+ .map(line => {
192
+ const [
193
+ paneId,
194
+ windowIndex,
195
+ paneIndex,
196
+ title,
197
+ currentCommand,
198
+ currentPath,
199
+ active,
200
+ dead,
201
+ pid
202
+ ] = line.split('\t');
203
+
204
+ return {
205
+ paneId,
206
+ windowIndex: Number(windowIndex),
207
+ paneIndex: Number(paneIndex),
208
+ title,
209
+ currentCommand,
210
+ currentPath,
211
+ active: active === '1',
212
+ dead: dead === '1',
213
+ pid: pid ? Number(pid) : null
214
+ };
215
+ });
216
+ }
217
+
218
+ function summarizeWorkerStates(workers) {
219
+ return workers.reduce((counts, worker) => {
220
+ const state = worker.status.state || 'unknown';
221
+ counts[state] = (counts[state] || 0) + 1;
222
+ return counts;
223
+ }, {});
224
+ }
225
+
226
+ function buildSessionSnapshot({ sessionName, coordinationDir, panes }) {
227
+ const workerSnapshots = loadWorkerSnapshots(coordinationDir);
228
+ const paneMap = new Map(panes.map(pane => [pane.title, pane]));
229
+
230
+ const workers = workerSnapshots.map(worker => ({
231
+ ...worker,
232
+ pane: paneMap.get(worker.workerSlug) || null
233
+ }));
234
+
235
+ return {
236
+ sessionName,
237
+ coordinationDir,
238
+ sessionActive: panes.length > 0,
239
+ paneCount: panes.length,
240
+ workerCount: workers.length,
241
+ workerStates: summarizeWorkerStates(workers),
242
+ panes,
243
+ workers
244
+ };
245
+ }
246
+
247
+ function resolveSnapshotTarget(targetPath, cwd = process.cwd()) {
248
+ const absoluteTarget = path.resolve(cwd, targetPath);
249
+
250
+ if (fs.existsSync(absoluteTarget) && fs.statSync(absoluteTarget).isFile()) {
251
+ const config = JSON.parse(fs.readFileSync(absoluteTarget, 'utf8'));
252
+ const repoRoot = path.resolve(config.repoRoot || cwd);
253
+ const coordinationRoot = path.resolve(
254
+ config.coordinationRoot || path.join(repoRoot, '.orchestration')
255
+ );
256
+
257
+ return {
258
+ sessionName: config.sessionName,
259
+ coordinationDir: path.join(coordinationRoot, config.sessionName),
260
+ repoRoot,
261
+ targetType: 'plan'
262
+ };
263
+ }
264
+
265
+ return {
266
+ sessionName: targetPath,
267
+ coordinationDir: path.join(cwd, '.claude', 'orchestration', targetPath),
268
+ repoRoot: cwd,
269
+ targetType: 'session'
270
+ };
271
+ }
272
+
273
+ function collectSessionSnapshot(targetPath, cwd = process.cwd()) {
274
+ const target = resolveSnapshotTarget(targetPath, cwd);
275
+ const panes = listTmuxPanes(target.sessionName);
276
+ const snapshot = buildSessionSnapshot({
277
+ sessionName: target.sessionName,
278
+ coordinationDir: target.coordinationDir,
279
+ panes
280
+ });
281
+
282
+ return {
283
+ ...snapshot,
284
+ repoRoot: target.repoRoot,
285
+ targetType: target.targetType
286
+ };
287
+ }
288
+
289
+ module.exports = {
290
+ buildSessionSnapshot,
291
+ collectSessionSnapshot,
292
+ listTmuxPanes,
293
+ loadWorkerSnapshots,
294
+ normalizeText: stripCodeTicks,
295
+ parseWorkerHandoff,
296
+ parseWorkerStatus,
297
+ parseWorkerTask,
298
+ resolveSnapshotTarget
299
+ };
@@ -0,0 +1,124 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * package-manager.js — Detect the active package manager (npm/pnpm/yarn/bun).
5
+ *
6
+ * Detection order:
7
+ * 1. CLAUDE_PACKAGE_MANAGER env var override
8
+ * 2. Presence of lock files in cwd
9
+ * 3. npm_execpath env var set by npm/yarn
10
+ * 4. Fallback: npm
11
+ */
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const { spawnSync } = require('child_process');
16
+
17
+ const LOCK_FILES = [
18
+ { file: 'bun.lockb', manager: 'bun' },
19
+ { file: 'yarn.lock', manager: 'yarn' },
20
+ { file: 'pnpm-lock.yaml', manager: 'pnpm' },
21
+ { file: 'package-lock.json', manager: 'npm' },
22
+ { file: 'npm-shrinkwrap.json', manager: 'npm' },
23
+ ];
24
+
25
+ /**
26
+ * Detect which package manager is in use.
27
+ * @param {string} [cwd] - Directory to check for lock files (defaults to process.cwd())
28
+ * @returns {'npm' | 'pnpm' | 'yarn' | 'bun'}
29
+ */
30
+ function detectPackageManager(cwd) {
31
+ // 1. Environment override
32
+ const override = process.env.CLAUDE_PACKAGE_MANAGER || process.env.SCC_PACKAGE_MANAGER;
33
+ if (override && ['npm', 'pnpm', 'yarn', 'bun'].includes(override.toLowerCase())) {
34
+ return override.toLowerCase();
35
+ }
36
+
37
+ const dir = cwd || process.cwd();
38
+
39
+ // 2. Lock file detection
40
+ for (const { file, manager } of LOCK_FILES) {
41
+ if (fs.existsSync(path.join(dir, file))) {
42
+ return manager;
43
+ }
44
+ }
45
+
46
+ // 3. npm_execpath (set by npm/yarn when running scripts)
47
+ const execPath = process.env.npm_execpath || '';
48
+ if (execPath.includes('yarn')) return 'yarn';
49
+ if (execPath.includes('pnpm')) return 'pnpm';
50
+ if (execPath.includes('bun')) return 'bun';
51
+
52
+ // 4. Try to detect installed package managers by running them
53
+ for (const pm of ['bun', 'pnpm', 'yarn']) {
54
+ const result = spawnSync(pm, ['--version'], { encoding: 'utf8', timeout: 2000 });
55
+ if (result.status === 0) return pm;
56
+ }
57
+
58
+ return 'npm';
59
+ }
60
+
61
+ /**
62
+ * Get the install command for a given package.
63
+ * @param {string} pkg - Package name (e.g., 'sql.js')
64
+ * @param {string} [manager] - Override package manager
65
+ * @returns {string} Full install command string
66
+ */
67
+ function getInstallCommand(pkg, manager) {
68
+ const pm = manager || detectPackageManager();
69
+ switch (pm) {
70
+ case 'yarn':
71
+ return `yarn add ${pkg}`;
72
+ case 'pnpm':
73
+ return `pnpm add ${pkg}`;
74
+ case 'bun':
75
+ return `bun add ${pkg}`;
76
+ case 'npm':
77
+ default:
78
+ return `npm install ${pkg}`;
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Get the run command for a script.
84
+ * @param {string} script - Script name
85
+ * @param {string} [manager] - Override package manager
86
+ * @returns {string}
87
+ */
88
+ function getRunCommand(script, manager) {
89
+ const pm = manager || detectPackageManager();
90
+ switch (pm) {
91
+ case 'yarn':
92
+ return `yarn ${script}`;
93
+ case 'pnpm':
94
+ return `pnpm run ${script}`;
95
+ case 'bun':
96
+ return `bun run ${script}`;
97
+ case 'npm':
98
+ default:
99
+ return `npm run ${script}`;
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Get the exec/dlx command (equivalent of npx).
105
+ * @param {string} bin - Binary to exec
106
+ * @param {string} [manager] - Override package manager
107
+ * @returns {string}
108
+ */
109
+ function getExecCommand(bin, manager) {
110
+ const pm = manager || detectPackageManager();
111
+ switch (pm) {
112
+ case 'yarn':
113
+ return `yarn dlx ${bin}`;
114
+ case 'pnpm':
115
+ return `pnpm dlx ${bin}`;
116
+ case 'bun':
117
+ return `bunx ${bin}`;
118
+ case 'npm':
119
+ default:
120
+ return `npx ${bin}`;
121
+ }
122
+ }
123
+
124
+ module.exports = { detectPackageManager, getInstallCommand, getRunCommand, getExecCommand };
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Salesforce project type and framework detection
3
+ *
4
+ * Cross-platform (Windows, macOS, Linux) project type detection
5
+ * by inspecting files in the working directory. Tailored for Salesforce
6
+ * projects with support for common web technologies used alongside SF.
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+
12
+ /**
13
+ * Salesforce project detection rules.
14
+ * Each rule checks for marker files specific to Salesforce project types.
15
+ */
16
+ const SF_PROJECT_RULES = [
17
+ {
18
+ type: 'sfdx',
19
+ markers: ['sfdx-project.json', 'sf-project.json'],
20
+ description: 'Salesforce DX Project'
21
+ },
22
+ {
23
+ type: 'lwc',
24
+ markers: ['force-app/main/default/lwc'],
25
+ description: 'Lightning Web Components'
26
+ },
27
+ {
28
+ type: 'apex',
29
+ markers: ['force-app/main/default/classes'],
30
+ description: 'Apex Classes'
31
+ },
32
+ {
33
+ type: 'aura',
34
+ markers: ['force-app/main/default/aura'],
35
+ description: 'Aura Components (Legacy)'
36
+ },
37
+ {
38
+ type: 'flow',
39
+ markers: ['force-app/main/default/flows'],
40
+ description: 'Salesforce Flows'
41
+ },
42
+ {
43
+ type: 'trigger',
44
+ markers: ['force-app/main/default/triggers'],
45
+ description: 'Apex Triggers'
46
+ }
47
+ ];
48
+
49
+ /**
50
+ * Language detection rules for non-Salesforce languages.
51
+ */
52
+ const LANGUAGE_RULES = [
53
+ {
54
+ type: 'typescript',
55
+ markers: ['tsconfig.json', 'tsconfig.build.json'],
56
+ extensions: ['.ts', '.tsx']
57
+ },
58
+ {
59
+ type: 'javascript',
60
+ markers: ['package.json', 'jsconfig.json'],
61
+ extensions: ['.js', '.jsx', '.mjs']
62
+ },
63
+ {
64
+ type: 'java',
65
+ markers: ['pom.xml', 'build.gradle', 'build.gradle.kts'],
66
+ extensions: ['.java']
67
+ },
68
+ {
69
+ type: 'python',
70
+ markers: ['requirements.txt', 'pyproject.toml', 'setup.py'],
71
+ extensions: ['.py']
72
+ }
73
+ ];
74
+
75
+ /**
76
+ * Framework detection rules relevant to Salesforce ecosystems.
77
+ */
78
+ const FRAMEWORK_RULES = [
79
+ // Salesforce frameworks
80
+ { framework: 'fflib', language: 'apex', markers: [], packageKeys: ['fflib'] },
81
+
82
+ // JavaScript/TypeScript frameworks (for LWC/Heroku)
83
+ { framework: 'react', language: 'typescript', markers: [], packageKeys: ['react'] },
84
+ { framework: 'express', language: 'javascript', markers: [], packageKeys: ['express'] },
85
+ { framework: 'nextjs', language: 'typescript', markers: ['next.config.js', 'next.config.mjs', 'next.config.ts'], packageKeys: ['next'] },
86
+
87
+ // Java frameworks (for SF Java SDK)
88
+ { framework: 'spring', language: 'java', markers: [], packageKeys: ['spring-boot', 'org.springframework'] }
89
+ ];
90
+
91
+ /**
92
+ * Check if a file or directory exists relative to the project directory
93
+ */
94
+ function fileExists(projectDir, filePath) {
95
+ try {
96
+ return fs.existsSync(path.join(projectDir, filePath));
97
+ } catch {
98
+ return false;
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Check if any file with given extension exists in the project root
104
+ */
105
+ function hasFileWithExtension(projectDir, extensions) {
106
+ try {
107
+ const entries = fs.readdirSync(projectDir, { withFileTypes: true });
108
+ return entries.some(entry => {
109
+ if (!entry.isFile()) return false;
110
+ const ext = path.extname(entry.name);
111
+ return extensions.includes(ext);
112
+ });
113
+ } catch {
114
+ return false;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Read and parse package.json dependencies
120
+ */
121
+ function getPackageJsonDeps(projectDir) {
122
+ try {
123
+ const pkgPath = path.join(projectDir, 'package.json');
124
+ if (!fs.existsSync(pkgPath)) return [];
125
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
126
+ return [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.devDependencies || {})];
127
+ } catch {
128
+ return [];
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Read sfdx-project.json for Salesforce project configuration
134
+ */
135
+ function getSfdxProjectConfig(projectDir) {
136
+ try {
137
+ const sfdxPath = path.join(projectDir, 'sfdx-project.json');
138
+ if (!fs.existsSync(sfdxPath)) {
139
+ const sfPath = path.join(projectDir, 'sf-project.json');
140
+ if (!fs.existsSync(sfPath)) return null;
141
+ return JSON.parse(fs.readFileSync(sfPath, 'utf8'));
142
+ }
143
+ return JSON.parse(fs.readFileSync(sfdxPath, 'utf8'));
144
+ } catch {
145
+ return null;
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Detect Salesforce project type, languages, and frameworks
151
+ * @param {string} [projectDir] - Project directory (defaults to cwd)
152
+ * @returns {{ sfTypes: string[], languages: string[], frameworks: string[], primary: string, projectDir: string, sfdxConfig: Object|null }}
153
+ */
154
+ function detectProjectType(projectDir) {
155
+ projectDir = projectDir || process.cwd();
156
+ const sfTypes = [];
157
+ const languages = [];
158
+ const frameworks = [];
159
+
160
+ // Step 1: Detect Salesforce project types
161
+ for (const rule of SF_PROJECT_RULES) {
162
+ const hasMarker = rule.markers.some(m => fileExists(projectDir, m));
163
+ if (hasMarker) {
164
+ sfTypes.push(rule.type);
165
+ }
166
+ }
167
+
168
+ // Step 2: Detect additional languages
169
+ for (const rule of LANGUAGE_RULES) {
170
+ const hasMarker = rule.markers.some(m => fileExists(projectDir, m));
171
+ const hasExt = rule.extensions.length > 0 && hasFileWithExtension(projectDir, rule.extensions);
172
+ if (hasMarker || hasExt) {
173
+ languages.push(rule.type);
174
+ }
175
+ }
176
+
177
+ // Deduplicate: if both typescript and javascript detected, keep typescript
178
+ if (languages.includes('typescript') && languages.includes('javascript')) {
179
+ const idx = languages.indexOf('javascript');
180
+ if (idx !== -1) languages.splice(idx, 1);
181
+ }
182
+
183
+ // Step 3: Detect frameworks
184
+ const npmDeps = getPackageJsonDeps(projectDir);
185
+
186
+ for (const rule of FRAMEWORK_RULES) {
187
+ const hasMarker = rule.markers.some(m => fileExists(projectDir, m));
188
+ let hasDep = false;
189
+ if (rule.packageKeys.length > 0 && (rule.language === 'typescript' || rule.language === 'javascript')) {
190
+ hasDep = rule.packageKeys.some(key => npmDeps.some(dep => dep.toLowerCase().includes(key.toLowerCase())));
191
+ }
192
+ if (hasMarker || hasDep) {
193
+ frameworks.push(rule.framework);
194
+ }
195
+ }
196
+
197
+ // Step 4: Determine primary type
198
+ let primary = 'unknown';
199
+ if (sfTypes.length > 0) {
200
+ primary = 'salesforce';
201
+ } else if (frameworks.length > 0) {
202
+ primary = frameworks[0];
203
+ } else if (languages.length > 0) {
204
+ primary = languages[0];
205
+ }
206
+
207
+ // Step 5: Read SFDX project config
208
+ const sfdxConfig = getSfdxProjectConfig(projectDir);
209
+
210
+ return {
211
+ sfTypes,
212
+ languages,
213
+ frameworks,
214
+ primary,
215
+ projectDir,
216
+ sfdxConfig
217
+ };
218
+ }
219
+
220
+ module.exports = {
221
+ detectProjectType,
222
+ SF_PROJECT_RULES,
223
+ LANGUAGE_RULES,
224
+ FRAMEWORK_RULES,
225
+ // Exported for testing
226
+ getPackageJsonDeps,
227
+ getSfdxProjectConfig
228
+ };