@cloudstreamsoftware/claude-tools 1.0.0 → 1.2.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 (190) hide show
  1. package/README.md +152 -37
  2. package/agents/INDEX.md +183 -0
  3. package/agents/architect.md +247 -0
  4. package/agents/build-error-resolver.md +555 -0
  5. package/agents/catalyst-deployer.md +132 -0
  6. package/agents/code-reviewer.md +121 -0
  7. package/agents/compliance-auditor.md +148 -0
  8. package/agents/creator-architect.md +395 -0
  9. package/agents/deluge-reviewer.md +98 -0
  10. package/agents/doc-updater.md +471 -0
  11. package/agents/e2e-runner.md +711 -0
  12. package/agents/planner.md +122 -0
  13. package/agents/refactor-cleaner.md +309 -0
  14. package/agents/security-reviewer.md +582 -0
  15. package/agents/tdd-guide.md +302 -0
  16. package/bin/cloudstream-setup.js +16 -6
  17. package/config/versions.json +63 -0
  18. package/dist/hooks/hooks.json +209 -0
  19. package/dist/index.js +47 -0
  20. package/dist/lib/asset-value.js +609 -0
  21. package/dist/lib/client-manager.js +300 -0
  22. package/dist/lib/command-matcher.js +242 -0
  23. package/dist/lib/cross-session-patterns.js +754 -0
  24. package/dist/lib/intent-classifier.js +1075 -0
  25. package/dist/lib/package-manager.js +374 -0
  26. package/dist/lib/recommendation-engine.js +597 -0
  27. package/dist/lib/session-memory.js +489 -0
  28. package/dist/lib/skill-effectiveness.js +486 -0
  29. package/dist/lib/skill-matcher.js +595 -0
  30. package/dist/lib/tutorial-metrics.js +242 -0
  31. package/dist/lib/tutorial-progress.js +209 -0
  32. package/dist/lib/tutorial-renderer.js +431 -0
  33. package/dist/lib/utils.js +380 -0
  34. package/dist/lib/verify-formatter.js +143 -0
  35. package/dist/lib/workflow-state.js +249 -0
  36. package/hooks/hooks.json +209 -0
  37. package/package.json +5 -1
  38. package/scripts/aggregate-sessions.js +290 -0
  39. package/scripts/branch-name-validator.js +291 -0
  40. package/scripts/build.js +101 -0
  41. package/scripts/commands/client-switch.js +231 -0
  42. package/scripts/deprecate-skill.js +610 -0
  43. package/scripts/diagnose.js +324 -0
  44. package/scripts/doc-freshness.js +168 -0
  45. package/scripts/generate-weekly-digest.js +393 -0
  46. package/scripts/health-check.js +270 -0
  47. package/scripts/hooks/credential-check.js +101 -0
  48. package/scripts/hooks/evaluate-session.js +81 -0
  49. package/scripts/hooks/pre-compact.js +66 -0
  50. package/scripts/hooks/prompt-analyzer.js +276 -0
  51. package/scripts/hooks/prompt-router.js +422 -0
  52. package/scripts/hooks/quality-gate-enforcer.js +371 -0
  53. package/scripts/hooks/session-end.js +156 -0
  54. package/scripts/hooks/session-start.js +195 -0
  55. package/scripts/hooks/skill-injector.js +333 -0
  56. package/scripts/hooks/suggest-compact.js +58 -0
  57. package/scripts/lib/asset-value.js +609 -0
  58. package/scripts/lib/client-manager.js +300 -0
  59. package/scripts/lib/command-matcher.js +242 -0
  60. package/scripts/lib/cross-session-patterns.js +754 -0
  61. package/scripts/lib/intent-classifier.js +1075 -0
  62. package/scripts/lib/package-manager.js +374 -0
  63. package/scripts/lib/recommendation-engine.js +597 -0
  64. package/scripts/lib/session-memory.js +489 -0
  65. package/scripts/lib/skill-effectiveness.js +486 -0
  66. package/scripts/lib/skill-matcher.js +595 -0
  67. package/scripts/lib/tutorial-metrics.js +242 -0
  68. package/scripts/lib/tutorial-progress.js +209 -0
  69. package/scripts/lib/tutorial-renderer.js +431 -0
  70. package/scripts/lib/utils.js +380 -0
  71. package/scripts/lib/verify-formatter.js +143 -0
  72. package/scripts/lib/workflow-state.js +249 -0
  73. package/scripts/onboard.js +363 -0
  74. package/scripts/quarterly-report.js +692 -0
  75. package/scripts/setup-package-manager.js +204 -0
  76. package/scripts/sync-upstream.js +391 -0
  77. package/scripts/test.js +108 -0
  78. package/scripts/tutorial-runner.js +351 -0
  79. package/scripts/validate-all.js +201 -0
  80. package/scripts/verifiers/agents.js +245 -0
  81. package/scripts/verifiers/config.js +186 -0
  82. package/scripts/verifiers/environment.js +123 -0
  83. package/scripts/verifiers/hooks.js +188 -0
  84. package/scripts/verifiers/index.js +38 -0
  85. package/scripts/verifiers/persistence.js +140 -0
  86. package/scripts/verifiers/plugin.js +215 -0
  87. package/scripts/verifiers/skills.js +209 -0
  88. package/scripts/verify-setup.js +164 -0
  89. package/skills/INDEX.md +157 -0
  90. package/skills/backend-patterns/SKILL.md +586 -0
  91. package/skills/backend-patterns/catalyst-patterns.md +128 -0
  92. package/skills/bigquery-patterns/SKILL.md +27 -0
  93. package/skills/bigquery-patterns/performance-optimization.md +518 -0
  94. package/skills/bigquery-patterns/query-patterns.md +372 -0
  95. package/skills/bigquery-patterns/schema-design.md +78 -0
  96. package/skills/cloudstream-project-template/SKILL.md +20 -0
  97. package/skills/cloudstream-project-template/structure.md +65 -0
  98. package/skills/coding-standards/SKILL.md +524 -0
  99. package/skills/coding-standards/deluge-standards.md +83 -0
  100. package/skills/compliance-patterns/SKILL.md +28 -0
  101. package/skills/compliance-patterns/hipaa/audit-requirements.md +251 -0
  102. package/skills/compliance-patterns/hipaa/baa-process.md +298 -0
  103. package/skills/compliance-patterns/hipaa/data-archival-strategy.md +387 -0
  104. package/skills/compliance-patterns/hipaa/phi-handling.md +52 -0
  105. package/skills/compliance-patterns/pci-dss/saq-a-requirements.md +307 -0
  106. package/skills/compliance-patterns/pci-dss/tokenization-patterns.md +382 -0
  107. package/skills/compliance-patterns/pci-dss/zoho-checkout-patterns.md +56 -0
  108. package/skills/compliance-patterns/soc2/access-controls.md +344 -0
  109. package/skills/compliance-patterns/soc2/audit-logging.md +458 -0
  110. package/skills/compliance-patterns/soc2/change-management.md +403 -0
  111. package/skills/compliance-patterns/soc2/deluge-execution-logging.md +407 -0
  112. package/skills/consultancy-workflows/SKILL.md +19 -0
  113. package/skills/consultancy-workflows/client-isolation.md +21 -0
  114. package/skills/consultancy-workflows/documentation-automation.md +454 -0
  115. package/skills/consultancy-workflows/handoff-procedures.md +257 -0
  116. package/skills/consultancy-workflows/knowledge-capture.md +513 -0
  117. package/skills/consultancy-workflows/time-tracking.md +26 -0
  118. package/skills/continuous-learning/SKILL.md +84 -0
  119. package/skills/continuous-learning/config.json +18 -0
  120. package/skills/continuous-learning/evaluate-session.sh +60 -0
  121. package/skills/continuous-learning-v2/SKILL.md +126 -0
  122. package/skills/continuous-learning-v2/config.json +61 -0
  123. package/skills/frontend-patterns/SKILL.md +635 -0
  124. package/skills/frontend-patterns/zoho-widget-patterns.md +103 -0
  125. package/skills/gcp-data-engineering/SKILL.md +36 -0
  126. package/skills/gcp-data-engineering/bigquery/performance-optimization.md +337 -0
  127. package/skills/gcp-data-engineering/dataflow/error-handling.md +496 -0
  128. package/skills/gcp-data-engineering/dataflow/pipeline-patterns.md +444 -0
  129. package/skills/gcp-data-engineering/dbt/model-organization.md +63 -0
  130. package/skills/gcp-data-engineering/dbt/testing-patterns.md +503 -0
  131. package/skills/gcp-data-engineering/medallion-architecture/bronze-layer.md +60 -0
  132. package/skills/gcp-data-engineering/medallion-architecture/gold-layer.md +311 -0
  133. package/skills/gcp-data-engineering/medallion-architecture/layer-transitions.md +517 -0
  134. package/skills/gcp-data-engineering/medallion-architecture/silver-layer.md +305 -0
  135. package/skills/gcp-data-engineering/zoho-to-gcp/data-extraction.md +543 -0
  136. package/skills/gcp-data-engineering/zoho-to-gcp/real-time-vs-batch.md +337 -0
  137. package/skills/security-review/SKILL.md +498 -0
  138. package/skills/security-review/compliance-checklist.md +53 -0
  139. package/skills/strategic-compact/SKILL.md +67 -0
  140. package/skills/tdd-workflow/SKILL.md +413 -0
  141. package/skills/tdd-workflow/zoho-testing.md +124 -0
  142. package/skills/tutorial/SKILL.md +249 -0
  143. package/skills/tutorial/docs/ACCESSIBILITY.md +169 -0
  144. package/skills/tutorial/lessons/00-philosophy-and-workflow.md +198 -0
  145. package/skills/tutorial/lessons/01-basics.md +81 -0
  146. package/skills/tutorial/lessons/02-training.md +86 -0
  147. package/skills/tutorial/lessons/03-commands.md +109 -0
  148. package/skills/tutorial/lessons/04-workflows.md +115 -0
  149. package/skills/tutorial/lessons/05-compliance.md +116 -0
  150. package/skills/tutorial/lessons/06-zoho.md +121 -0
  151. package/skills/tutorial/lessons/07-hooks-system.md +277 -0
  152. package/skills/tutorial/lessons/08-mcp-servers.md +316 -0
  153. package/skills/tutorial/lessons/09-client-management.md +215 -0
  154. package/skills/tutorial/lessons/10-testing-e2e.md +260 -0
  155. package/skills/tutorial/lessons/11-skills-deep-dive.md +272 -0
  156. package/skills/tutorial/lessons/12-rules-system.md +326 -0
  157. package/skills/tutorial/lessons/13-golden-standard-graduation.md +213 -0
  158. package/skills/tutorial/lessons/14-fork-setup-and-sync.md +312 -0
  159. package/skills/tutorial/lessons/15-living-examples-system.md +221 -0
  160. package/skills/tutorial/tracks/accelerated/README.md +134 -0
  161. package/skills/tutorial/tracks/accelerated/assessment/checkpoint-1.md +161 -0
  162. package/skills/tutorial/tracks/accelerated/assessment/checkpoint-2.md +175 -0
  163. package/skills/tutorial/tracks/accelerated/day-1-core-concepts.md +234 -0
  164. package/skills/tutorial/tracks/accelerated/day-2-essential-commands.md +270 -0
  165. package/skills/tutorial/tracks/accelerated/day-3-workflow-mastery.md +305 -0
  166. package/skills/tutorial/tracks/accelerated/day-4-compliance-zoho.md +304 -0
  167. package/skills/tutorial/tracks/accelerated/day-5-hooks-skills.md +344 -0
  168. package/skills/tutorial/tracks/accelerated/day-6-client-testing.md +386 -0
  169. package/skills/tutorial/tracks/accelerated/day-7-graduation.md +369 -0
  170. package/skills/zoho-patterns/CHANGELOG.md +108 -0
  171. package/skills/zoho-patterns/SKILL.md +446 -0
  172. package/skills/zoho-patterns/analytics/dashboard-patterns.md +352 -0
  173. package/skills/zoho-patterns/analytics/zoho-to-bigquery-pipeline.md +427 -0
  174. package/skills/zoho-patterns/catalyst/appsail-deployment.md +349 -0
  175. package/skills/zoho-patterns/catalyst/context-close-patterns.md +354 -0
  176. package/skills/zoho-patterns/catalyst/cron-batch-processing.md +374 -0
  177. package/skills/zoho-patterns/catalyst/function-patterns.md +439 -0
  178. package/skills/zoho-patterns/creator/form-design.md +304 -0
  179. package/skills/zoho-patterns/creator/publish-api-patterns.md +313 -0
  180. package/skills/zoho-patterns/creator/widget-integration.md +306 -0
  181. package/skills/zoho-patterns/creator/workflow-automation.md +253 -0
  182. package/skills/zoho-patterns/deluge/api-patterns.md +468 -0
  183. package/skills/zoho-patterns/deluge/batch-processing.md +403 -0
  184. package/skills/zoho-patterns/deluge/cross-app-integration.md +356 -0
  185. package/skills/zoho-patterns/deluge/error-handling.md +423 -0
  186. package/skills/zoho-patterns/deluge/syntax-reference.md +65 -0
  187. package/skills/zoho-patterns/integration/cors-proxy-architecture.md +426 -0
  188. package/skills/zoho-patterns/integration/crm-books-native-sync.md +277 -0
  189. package/skills/zoho-patterns/integration/oauth-token-management.md +461 -0
  190. package/skills/zoho-patterns/integration/zoho-flow-patterns.md +334 -0
@@ -0,0 +1,290 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Cross-Session Aggregator
4
+ *
5
+ * Main entry point for aggregating session data across multiple sessions.
6
+ * Detects patterns, analyzes trends, and generates recommendations.
7
+ *
8
+ * Usage:
9
+ * node scripts/aggregate-sessions.js [--days=30] [--output=json|md]
10
+ *
11
+ * Options:
12
+ * --days Analysis window in days (default: 30)
13
+ * --output Output format: json or md (default: json)
14
+ * --force Run even if recently run
15
+ */
16
+
17
+ const path = require('path');
18
+ const fs = require('fs');
19
+ const {
20
+ getClaudeDir,
21
+ ensureDir,
22
+ writeFile,
23
+ getDateString,
24
+ getDateTimeString,
25
+ log,
26
+ } = require('./lib/utils');
27
+
28
+ const {
29
+ analyzeAllSessions,
30
+ detectCrossSessionPatterns,
31
+ analyzeByTechnology,
32
+ analyzeByComplianceMode,
33
+ analyzeTrends,
34
+ buildSkillCorrectionMatrix,
35
+ saveAggregatedData,
36
+ getAggregationStatus,
37
+ THRESHOLDS,
38
+ } = require('./lib/cross-session-patterns');
39
+
40
+ const {
41
+ generateRecommendations,
42
+ clearExpiredRecommendations,
43
+ formatRecommendations,
44
+ } = require('./lib/recommendation-engine');
45
+
46
+ // Parse command line arguments
47
+ function parseArgs() {
48
+ const args = process.argv.slice(2);
49
+ const options = {
50
+ days: 30,
51
+ output: 'json',
52
+ force: false,
53
+ };
54
+
55
+ for (const arg of args) {
56
+ if (arg.startsWith('--days=')) {
57
+ options.days = parseInt(arg.split('=')[1], 10) || 30;
58
+ } else if (arg.startsWith('--output=')) {
59
+ options.output = arg.split('=')[1] || 'json';
60
+ } else if (arg === '--force') {
61
+ options.force = true;
62
+ }
63
+ }
64
+
65
+ return options;
66
+ }
67
+
68
+ /**
69
+ * Generate markdown report from aggregated data
70
+ */
71
+ function generateMarkdownReport(data, options) {
72
+ const reportsDir = path.join(getClaudeDir(), 'knowledge', 'reports');
73
+ ensureDir(reportsDir);
74
+
75
+ const date = getDateString();
76
+ const reportPath = path.join(reportsDir, `aggregation-${date}.md`);
77
+
78
+ let md = `# Cross-Session Aggregation Report\n\n`;
79
+ md += `**Generated:** ${getDateTimeString()}\n`;
80
+ md += `**Analysis Window:** ${options.days} days\n\n`;
81
+
82
+ // Summary
83
+ md += `## Summary\n\n`;
84
+ md += `- Sessions analyzed: ${data.summary.sessionCount}\n`;
85
+ md += `- Total corrections: ${data.summary.correctionCount}\n`;
86
+ md += `- High-confidence patterns: ${data.patterns.highConfidence.length}\n`;
87
+ md += `- Recommendations generated: ${data.recommendations.length}\n\n`;
88
+
89
+ // High-confidence patterns
90
+ if (data.patterns.highConfidence.length > 0) {
91
+ md += `## High-Confidence Patterns\n\n`;
92
+ md += `| Pattern | Category | Sessions | Confidence |\n`;
93
+ md += `|---------|----------|----------|------------|\n`;
94
+
95
+ for (const p of data.patterns.highConfidence.slice(0, 10)) {
96
+ md += `| ${truncate(p.original, 40)} | ${p.category} | ${p.sessionCount} | ${Math.round(p.confidence * 100)}% |\n`;
97
+ }
98
+ md += '\n';
99
+ }
100
+
101
+ // Trends
102
+ if (data.trends.improving.length > 0 || data.trends.worsening.length > 0) {
103
+ md += `## Trends\n\n`;
104
+
105
+ if (data.trends.improving.length > 0) {
106
+ md += `### Improving\n\n`;
107
+ for (const t of data.trends.improving.slice(0, 5)) {
108
+ md += `- ${truncate(t.original, 50)}: ${t.percentChange}%\n`;
109
+ }
110
+ md += '\n';
111
+ }
112
+
113
+ if (data.trends.worsening.length > 0) {
114
+ md += `### Worsening\n\n`;
115
+ for (const t of data.trends.worsening.slice(0, 5)) {
116
+ md += `- ${truncate(t.original, 50)}: +${t.percentChange}%\n`;
117
+ }
118
+ md += '\n';
119
+ }
120
+ }
121
+
122
+ // Technology patterns
123
+ if (Object.keys(data.techPatterns).length > 0) {
124
+ md += `## Technology-Specific Patterns\n\n`;
125
+
126
+ for (const [tech, techData] of Object.entries(data.techPatterns)) {
127
+ md += `### ${tech}\n\n`;
128
+ md += `- Sessions: ${techData.sessionCount}\n`;
129
+ md += `- Correction rate: ${techData.correctionRate.toFixed(1)}/session\n`;
130
+
131
+ if (techData.topIssues.length > 0) {
132
+ md += `- Top issue: ${truncate(techData.topIssues[0].original, 40)} (${techData.topIssues[0].count}x)\n`;
133
+ }
134
+ md += '\n';
135
+ }
136
+ }
137
+
138
+ // Recommendations
139
+ if (data.recommendations.length > 0) {
140
+ md += `## Recommendations\n\n`;
141
+ md += formatRecommendations(data.recommendations.slice(0, 5));
142
+ }
143
+
144
+ writeFile(reportPath, md);
145
+ log(`[Aggregator] Report saved to: ${reportPath}`);
146
+
147
+ return reportPath;
148
+ }
149
+
150
+ /**
151
+ * Truncate string for display
152
+ */
153
+ function truncate(str, length) {
154
+ if (!str) return '';
155
+ if (str.length <= length) return str;
156
+ return str.substring(0, length - 3) + '...';
157
+ }
158
+
159
+ /**
160
+ * Main aggregation function
161
+ */
162
+ async function main() {
163
+ const options = parseArgs();
164
+
165
+ log('[Aggregator] Starting cross-session analysis...');
166
+
167
+ // Check if we need to run
168
+ if (!options.force) {
169
+ const status = getAggregationStatus();
170
+ if (!status.needsUpdate) {
171
+ log(`[Aggregator] Already up to date (last run: ${status.lastRun})`);
172
+ log(`[Aggregator] Use --force to run anyway`);
173
+ return;
174
+ }
175
+ }
176
+
177
+ // 1. Load and analyze all sessions
178
+ const { sessions, corrections, summary } = analyzeAllSessions();
179
+
180
+ if (summary.insufficient) {
181
+ log(
182
+ `[Aggregator] Insufficient sessions (${summary.sessionCount}). Need at least ${THRESHOLDS.MIN_SESSIONS_FOR_ANALYSIS}.`
183
+ );
184
+ return;
185
+ }
186
+
187
+ log(`[Aggregator] Loaded ${sessions.length} sessions with ${corrections.length} corrections`);
188
+
189
+ // 2. Detect cross-session patterns
190
+ const patterns = detectCrossSessionPatterns(THRESHOLDS.MIN_SESSIONS_FOR_PATTERN);
191
+ log(`[Aggregator] Found ${patterns.highConfidence.length} high-confidence patterns`);
192
+ log(`[Aggregator] Found ${patterns.emerging.length} emerging patterns`);
193
+
194
+ // 3. Analyze by context
195
+ const techPatterns = analyzeByTechnology();
196
+ const compliancePatterns = analyzeByComplianceMode();
197
+ log(`[Aggregator] Analyzed ${Object.keys(techPatterns).length} technologies`);
198
+
199
+ // 4. Analyze trends
200
+ const trends = analyzeTrends(options.days);
201
+ log(
202
+ `[Aggregator] Trends: ${trends.improving.length} improving, ${trends.worsening.length} worsening`
203
+ );
204
+
205
+ // 5. Build skill-correction matrix
206
+ const skillMatrix = buildSkillCorrectionMatrix();
207
+ log(`[Aggregator] Built skill matrix with ${Object.keys(skillMatrix).length} skills`);
208
+
209
+ // 6. Clear expired recommendations first
210
+ const expiredCount = clearExpiredRecommendations();
211
+ if (expiredCount > 0) {
212
+ log(`[Aggregator] Cleared ${expiredCount} expired recommendations`);
213
+ }
214
+
215
+ // 7. Generate recommendations
216
+ const { recommendations, summary: recSummary } = generateRecommendations({
217
+ patterns,
218
+ trends,
219
+ skillMatrix,
220
+ techPatterns,
221
+ });
222
+ log(
223
+ `[Aggregator] Generated ${recSummary.total} recommendations (${recSummary.high} high, ${recSummary.medium} medium)`
224
+ );
225
+
226
+ // 8. Prepare aggregated data
227
+ const aggregatedData = {
228
+ summary,
229
+ patterns,
230
+ techPatterns,
231
+ compliancePatterns,
232
+ trends,
233
+ skillMatrix,
234
+ recommendations,
235
+ };
236
+
237
+ // 9. Save results
238
+ saveAggregatedData({
239
+ patternLibrary: patterns,
240
+ contextPatterns: { techPatterns, compliancePatterns },
241
+ trendAnalysis: trends,
242
+ skillCorrectionMatrix: skillMatrix,
243
+ recommendations,
244
+ });
245
+
246
+ log('[Aggregator] Saved aggregated data');
247
+
248
+ // 10. Generate report if requested
249
+ if (options.output === 'md') {
250
+ generateMarkdownReport(aggregatedData, options);
251
+ }
252
+
253
+ // 11. Output summary
254
+ log('\n[Aggregator] === AGGREGATION COMPLETE ===\n');
255
+ log(`Sessions analyzed: ${sessions.length}`);
256
+ log(`High-confidence patterns: ${patterns.highConfidence.length}`);
257
+ log(`Emerging patterns: ${patterns.emerging.length}`);
258
+ log(`Trends improving: ${trends.improving.length}`);
259
+ log(`Trends worsening: ${trends.worsening.length}`);
260
+ log(`Recommendations: ${recommendations.length}`);
261
+
262
+ if (patterns.highConfidence.length > 0) {
263
+ log('\nTop patterns:');
264
+ for (const p of patterns.highConfidence.slice(0, 3)) {
265
+ log(
266
+ ` - ${truncate(p.original, 50)} (${p.sessionCount} sessions, ${Math.round(p.confidence * 100)}%)`
267
+ );
268
+ }
269
+ }
270
+
271
+ if (recommendations.length > 0) {
272
+ log('\nTop recommendations:');
273
+ for (const r of recommendations.slice(0, 3)) {
274
+ const emoji = r.priority === 'high' ? '🔴' : r.priority === 'medium' ? '🟠' : '🟡';
275
+ log(` ${emoji} ${r.title}`);
276
+ }
277
+ }
278
+
279
+ log('\n[Aggregator] Done');
280
+ }
281
+
282
+ // Run if called directly
283
+ if (require.main === module) {
284
+ main().catch((err) => {
285
+ log(`[Aggregator] Error: ${err.message}`);
286
+ process.exit(1);
287
+ });
288
+ }
289
+
290
+ module.exports = { main };
@@ -0,0 +1,291 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Branch Name Validator (Phase 7)
4
+ *
5
+ * Validates and creates branch names following CloudStream conventions:
6
+ * - feature/[CLIENT]/[description]
7
+ * - fix/[CLIENT]/[description]
8
+ * - hotfix/[CLIENT]/[description]
9
+ * - docs/[description]
10
+ * - chore/[description]
11
+ *
12
+ * Usage:
13
+ * node branch-name-validator.js [branch-name]
14
+ * node branch-name-validator.js --current
15
+ */
16
+
17
+ const { execSync } = require('child_process');
18
+
19
+ /**
20
+ * Valid branch name patterns.
21
+ * @type {RegExp[]}
22
+ */
23
+ const VALID_PATTERNS = [
24
+ /^feature\/[A-Z]{2,5}\/[a-z0-9-]+$/,
25
+ /^fix\/[A-Z]{2,5}\/[a-z0-9-]+$/,
26
+ /^hotfix\/[A-Z]{2,5}\/[a-z0-9-]+$/,
27
+ /^docs\/[a-z0-9-]+$/,
28
+ /^chore\/[a-z0-9-]+$/,
29
+ /^main$/,
30
+ /^develop$/,
31
+ ];
32
+
33
+ /**
34
+ * Branch types that require a client ID.
35
+ * @type {string[]}
36
+ */
37
+ const CLIENT_REQUIRED_TYPES = ['feature', 'fix', 'hotfix'];
38
+
39
+ /**
40
+ * Valid branch types.
41
+ * @type {string[]}
42
+ */
43
+ const VALID_TYPES = ['feature', 'fix', 'hotfix', 'docs', 'chore'];
44
+
45
+ /**
46
+ * Check if a branch name is valid.
47
+ * @param {string} branchName - The branch name to validate
48
+ * @returns {boolean} True if valid
49
+ */
50
+ function isValidBranchName(branchName) {
51
+ if (!branchName || typeof branchName !== 'string') {
52
+ return false;
53
+ }
54
+
55
+ return VALID_PATTERNS.some((pattern) => pattern.test(branchName));
56
+ }
57
+
58
+ /**
59
+ * Validate a branch name and return detailed result.
60
+ * @param {string} branchName - The branch name to validate
61
+ * @returns {object} Validation result with valid, error, suggestion, type, client, description
62
+ */
63
+ function validateBranchName(branchName) {
64
+ if (!branchName || typeof branchName !== 'string') {
65
+ return {
66
+ valid: false,
67
+ error: 'Branch name is required',
68
+ suggestion:
69
+ 'Use: feature/CLIENT/description, fix/CLIENT/description, docs/description, or chore/description',
70
+ type: null,
71
+ client: null,
72
+ description: null,
73
+ };
74
+ }
75
+
76
+ // Check if valid
77
+ if (isValidBranchName(branchName)) {
78
+ // Parse the branch name to extract components
79
+ const parsed = parseBranchName(branchName);
80
+ return {
81
+ valid: true,
82
+ error: null,
83
+ suggestion: null,
84
+ ...parsed,
85
+ };
86
+ }
87
+
88
+ // Generate helpful error message
89
+ const suggestion = generateSuggestion(branchName);
90
+
91
+ return {
92
+ valid: false,
93
+ error: `Branch name "${branchName}" does not follow CloudStream conventions`,
94
+ suggestion,
95
+ type: null,
96
+ client: null,
97
+ description: null,
98
+ };
99
+ }
100
+
101
+ /**
102
+ * Parse a valid branch name into components.
103
+ * @param {string} branchName - Valid branch name
104
+ * @returns {object} Parsed components
105
+ */
106
+ function parseBranchName(branchName) {
107
+ if (branchName === 'main' || branchName === 'develop') {
108
+ return { type: branchName, client: null, description: null };
109
+ }
110
+
111
+ const parts = branchName.split('/');
112
+
113
+ if (parts.length === 2) {
114
+ // docs/description or chore/description
115
+ return {
116
+ type: parts[0],
117
+ client: null,
118
+ description: parts[1],
119
+ };
120
+ }
121
+
122
+ if (parts.length === 3) {
123
+ // feature/CLIENT/description
124
+ return {
125
+ type: parts[0],
126
+ client: parts[1],
127
+ description: parts[2],
128
+ };
129
+ }
130
+
131
+ return { type: null, client: null, description: null };
132
+ }
133
+
134
+ /**
135
+ * Generate a suggestion for an invalid branch name.
136
+ * @param {string} branchName - Invalid branch name
137
+ * @returns {string} Suggestion message
138
+ */
139
+ function generateSuggestion(branchName) {
140
+ const parts = branchName.split('/');
141
+
142
+ if (parts.length === 1) {
143
+ return 'Try: feature/CSS/your-feature-name or docs/your-doc-name';
144
+ }
145
+
146
+ const type = parts[0].toLowerCase();
147
+
148
+ if (VALID_TYPES.includes(type)) {
149
+ if (CLIENT_REQUIRED_TYPES.includes(type) && parts.length === 2) {
150
+ return `${type}/ branches require a CLIENT ID: ${type}/CSS/${parts[1] || 'description'}`;
151
+ }
152
+ }
153
+
154
+ return 'Valid formats: feature/CLIENT/description, fix/CLIENT/description, docs/description, chore/description';
155
+ }
156
+
157
+ /**
158
+ * Convert a string to kebab-case.
159
+ * @param {string} str - Input string
160
+ * @returns {string} Kebab-case string
161
+ */
162
+ function toKebabCase(str) {
163
+ return str
164
+ .toLowerCase()
165
+ .replace(/[^a-z0-9\s-]/g, '') // Remove special chars
166
+ .replace(/\s+/g, '-') // Replace spaces with hyphens
167
+ .replace(/-+/g, '-') // Remove consecutive hyphens
168
+ .replace(/^-|-$/g, ''); // Remove leading/trailing hyphens
169
+ }
170
+
171
+ /**
172
+ * Create a properly formatted branch name.
173
+ * @param {string} type - Branch type (feature, fix, hotfix, docs, chore)
174
+ * @param {string|null} client - Client ID (required for feature, fix, hotfix)
175
+ * @param {string} description - Branch description
176
+ * @returns {string} Formatted branch name
177
+ * @throws {Error} If invalid type or missing required client
178
+ */
179
+ function createBranchName(type, client, description) {
180
+ if (!VALID_TYPES.includes(type)) {
181
+ throw new Error(`Invalid branch type: ${type}. Valid types: ${VALID_TYPES.join(', ')}`);
182
+ }
183
+
184
+ const kebabDescription = toKebabCase(description);
185
+
186
+ if (CLIENT_REQUIRED_TYPES.includes(type)) {
187
+ if (!client) {
188
+ throw new Error(
189
+ `Client ID required for ${type} branches. Use: ${type}/CLIENT/${kebabDescription}`
190
+ );
191
+ }
192
+ return `${type}/${client.toUpperCase()}/${kebabDescription}`;
193
+ }
194
+
195
+ // docs and chore don't require client
196
+ return `${type}/${kebabDescription}`;
197
+ }
198
+
199
+ /**
200
+ * Get the current git branch name.
201
+ * @returns {string|null} Current branch name or null if not in a git repo
202
+ */
203
+ function getCurrentBranch() {
204
+ try {
205
+ return execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim();
206
+ } catch {
207
+ return null;
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Main CLI entry point.
213
+ */
214
+ function main() {
215
+ const args = process.argv.slice(2);
216
+
217
+ if (args.includes('--help') || args.includes('-h')) {
218
+ console.log(`
219
+ Branch Name Validator
220
+
221
+ Usage:
222
+ node branch-name-validator.js <branch-name> Validate a specific branch name
223
+ node branch-name-validator.js --current Validate current git branch
224
+ node branch-name-validator.js --help Show this help
225
+
226
+ Valid branch formats:
227
+ feature/CLIENT/description New feature (e.g., feature/CSS/add-login)
228
+ fix/CLIENT/description Bug fix (e.g., fix/ACME/bug-123)
229
+ hotfix/CLIENT/description Critical fix (e.g., hotfix/CSS/urgent)
230
+ docs/description Documentation (e.g., docs/update-readme)
231
+ chore/description Maintenance (e.g., chore/cleanup)
232
+ main Main branch
233
+ develop Development branch
234
+ `);
235
+ process.exit(0);
236
+ }
237
+
238
+ let branchName;
239
+
240
+ if (args.includes('--current') || args.includes('-c')) {
241
+ branchName = getCurrentBranch();
242
+ if (!branchName) {
243
+ console.error('Error: Not in a git repository');
244
+ process.exit(1);
245
+ }
246
+ } else if (args.length > 0) {
247
+ branchName = args[0];
248
+ } else {
249
+ // Default to current branch
250
+ branchName = getCurrentBranch();
251
+ if (!branchName) {
252
+ console.error('Error: No branch name provided and not in a git repository');
253
+ process.exit(1);
254
+ }
255
+ }
256
+
257
+ const result = validateBranchName(branchName);
258
+
259
+ if (result.valid) {
260
+ console.log(`✓ Branch "${branchName}" is valid`);
261
+ if (result.type && result.type !== 'main' && result.type !== 'develop') {
262
+ console.log(` Type: ${result.type}`);
263
+ if (result.client) console.log(` Client: ${result.client}`);
264
+ if (result.description) console.log(` Description: ${result.description}`);
265
+ }
266
+ process.exit(0);
267
+ } else {
268
+ console.error(`✗ ${result.error}`);
269
+ if (result.suggestion) {
270
+ console.error(` Suggestion: ${result.suggestion}`);
271
+ }
272
+ process.exit(1);
273
+ }
274
+ }
275
+
276
+ // Export for testing
277
+ module.exports = {
278
+ VALID_PATTERNS,
279
+ VALID_TYPES,
280
+ CLIENT_REQUIRED_TYPES,
281
+ isValidBranchName,
282
+ validateBranchName,
283
+ createBranchName,
284
+ toKebabCase,
285
+ getCurrentBranch,
286
+ };
287
+
288
+ // Run CLI if executed directly
289
+ if (require.main === module) {
290
+ main();
291
+ }
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Build script for @cloudstreamsoftware/claude-tools
4
+ * Creates the dist directory with entry point and copies necessary files
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ const ROOT = path.resolve(__dirname, '..');
11
+ const DIST = path.join(ROOT, 'dist');
12
+
13
+ // Ensure dist directory exists
14
+ if (!fs.existsSync(DIST)) {
15
+ fs.mkdirSync(DIST, { recursive: true });
16
+ }
17
+
18
+ // Create dist/index.js entry point
19
+ const indexContent = `/**
20
+ * @cloudstreamsoftware/claude-tools
21
+ * CloudStream Claude Code productivity tools
22
+ */
23
+
24
+ 'use strict';
25
+
26
+ const path = require('path');
27
+
28
+ // Export package paths for programmatic use
29
+ module.exports = {
30
+ // Root directory of the installed package
31
+ root: path.resolve(__dirname, '..'),
32
+
33
+ // Paths to key directories
34
+ paths: {
35
+ hooks: path.resolve(__dirname, '..', 'hooks'),
36
+ scripts: path.resolve(__dirname, '..', 'scripts'),
37
+ skills: path.resolve(__dirname, '..', 'skills'),
38
+ agents: path.resolve(__dirname, '..', 'agents'),
39
+ config: path.resolve(__dirname, '..', 'config'),
40
+ },
41
+
42
+ // Get the hooks configuration
43
+ getHooksConfig: function() {
44
+ const hooksPath = path.join(this.paths.hooks, 'hooks.json');
45
+ return require(hooksPath);
46
+ },
47
+
48
+ // Get available skills
49
+ getSkills: function() {
50
+ const skillsDir = this.paths.skills;
51
+ if (!require('fs').existsSync(skillsDir)) return [];
52
+ return require('fs').readdirSync(skillsDir, { withFileTypes: true })
53
+ .filter(d => d.isDirectory())
54
+ .map(d => d.name);
55
+ },
56
+
57
+ // Get available agents
58
+ getAgents: function() {
59
+ const agentsDir = this.paths.agents;
60
+ if (!require('fs').existsSync(agentsDir)) return [];
61
+ return require('fs').readdirSync(agentsDir)
62
+ .filter(f => f.endsWith('.md'))
63
+ .map(f => f.replace('.md', ''));
64
+ }
65
+ };
66
+ `;
67
+
68
+ fs.writeFileSync(path.join(DIST, 'index.js'), indexContent);
69
+ console.log('✓ Created dist/index.js');
70
+
71
+ // Create dist/hooks directory and copy hooks.json
72
+ const distHooks = path.join(DIST, 'hooks');
73
+ if (!fs.existsSync(distHooks)) {
74
+ fs.mkdirSync(distHooks, { recursive: true });
75
+ }
76
+
77
+ const hooksSource = path.join(ROOT, 'hooks', 'hooks.json');
78
+ if (fs.existsSync(hooksSource)) {
79
+ fs.copyFileSync(hooksSource, path.join(distHooks, 'hooks.json'));
80
+ console.log('✓ Copied hooks/hooks.json to dist/hooks/');
81
+ }
82
+
83
+ // Create dist/lib directory for any compiled utilities
84
+ const distLib = path.join(DIST, 'lib');
85
+ if (!fs.existsSync(distLib)) {
86
+ fs.mkdirSync(distLib, { recursive: true });
87
+ }
88
+
89
+ // Copy lib utilities to dist/lib
90
+ const libSource = path.join(ROOT, 'scripts', 'lib');
91
+ if (fs.existsSync(libSource)) {
92
+ const libFiles = fs.readdirSync(libSource).filter(f => f.endsWith('.js'));
93
+ libFiles.forEach(file => {
94
+ fs.copyFileSync(path.join(libSource, file), path.join(distLib, file));
95
+ });
96
+ console.log(`✓ Copied ${libFiles.length} lib files to dist/lib/`);
97
+ }
98
+
99
+ console.log('\n✅ Build complete!');
100
+ console.log(` Package: @cloudstreamsoftware/claude-tools`);
101
+ console.log(` Output: ${DIST}`);