@cloudstreamsoftware/claude-tools 1.0.0 → 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.
- package/README.md +152 -37
- package/agents/INDEX.md +183 -0
- package/agents/architect.md +247 -0
- package/agents/build-error-resolver.md +555 -0
- package/agents/catalyst-deployer.md +132 -0
- package/agents/code-reviewer.md +121 -0
- package/agents/compliance-auditor.md +148 -0
- package/agents/creator-architect.md +395 -0
- package/agents/deluge-reviewer.md +98 -0
- package/agents/doc-updater.md +471 -0
- package/agents/e2e-runner.md +711 -0
- package/agents/planner.md +122 -0
- package/agents/refactor-cleaner.md +309 -0
- package/agents/security-reviewer.md +582 -0
- package/agents/tdd-guide.md +302 -0
- package/config/versions.json +63 -0
- package/dist/hooks/hooks.json +209 -0
- package/dist/index.js +47 -0
- package/dist/lib/asset-value.js +609 -0
- package/dist/lib/client-manager.js +300 -0
- package/dist/lib/command-matcher.js +242 -0
- package/dist/lib/cross-session-patterns.js +754 -0
- package/dist/lib/intent-classifier.js +1075 -0
- package/dist/lib/package-manager.js +374 -0
- package/dist/lib/recommendation-engine.js +597 -0
- package/dist/lib/session-memory.js +489 -0
- package/dist/lib/skill-effectiveness.js +486 -0
- package/dist/lib/skill-matcher.js +595 -0
- package/dist/lib/tutorial-metrics.js +242 -0
- package/dist/lib/tutorial-progress.js +209 -0
- package/dist/lib/tutorial-renderer.js +431 -0
- package/dist/lib/utils.js +380 -0
- package/dist/lib/verify-formatter.js +143 -0
- package/dist/lib/workflow-state.js +249 -0
- package/hooks/hooks.json +209 -0
- package/package.json +5 -1
- package/scripts/aggregate-sessions.js +290 -0
- package/scripts/branch-name-validator.js +291 -0
- package/scripts/build.js +101 -0
- package/scripts/commands/client-switch.js +231 -0
- package/scripts/deprecate-skill.js +610 -0
- package/scripts/diagnose.js +324 -0
- package/scripts/doc-freshness.js +168 -0
- package/scripts/generate-weekly-digest.js +393 -0
- package/scripts/health-check.js +270 -0
- package/scripts/hooks/credential-check.js +101 -0
- package/scripts/hooks/evaluate-session.js +81 -0
- package/scripts/hooks/pre-compact.js +66 -0
- package/scripts/hooks/prompt-analyzer.js +276 -0
- package/scripts/hooks/prompt-router.js +422 -0
- package/scripts/hooks/quality-gate-enforcer.js +371 -0
- package/scripts/hooks/session-end.js +156 -0
- package/scripts/hooks/session-start.js +195 -0
- package/scripts/hooks/skill-injector.js +333 -0
- package/scripts/hooks/suggest-compact.js +58 -0
- package/scripts/lib/asset-value.js +609 -0
- package/scripts/lib/client-manager.js +300 -0
- package/scripts/lib/command-matcher.js +242 -0
- package/scripts/lib/cross-session-patterns.js +754 -0
- package/scripts/lib/intent-classifier.js +1075 -0
- package/scripts/lib/package-manager.js +374 -0
- package/scripts/lib/recommendation-engine.js +597 -0
- package/scripts/lib/session-memory.js +489 -0
- package/scripts/lib/skill-effectiveness.js +486 -0
- package/scripts/lib/skill-matcher.js +595 -0
- package/scripts/lib/tutorial-metrics.js +242 -0
- package/scripts/lib/tutorial-progress.js +209 -0
- package/scripts/lib/tutorial-renderer.js +431 -0
- package/scripts/lib/utils.js +380 -0
- package/scripts/lib/verify-formatter.js +143 -0
- package/scripts/lib/workflow-state.js +249 -0
- package/scripts/onboard.js +363 -0
- package/scripts/quarterly-report.js +692 -0
- package/scripts/setup-package-manager.js +204 -0
- package/scripts/sync-upstream.js +391 -0
- package/scripts/test.js +108 -0
- package/scripts/tutorial-runner.js +351 -0
- package/scripts/validate-all.js +201 -0
- package/scripts/verifiers/agents.js +245 -0
- package/scripts/verifiers/config.js +186 -0
- package/scripts/verifiers/environment.js +123 -0
- package/scripts/verifiers/hooks.js +188 -0
- package/scripts/verifiers/index.js +38 -0
- package/scripts/verifiers/persistence.js +140 -0
- package/scripts/verifiers/plugin.js +215 -0
- package/scripts/verifiers/skills.js +209 -0
- package/scripts/verify-setup.js +164 -0
- package/skills/INDEX.md +157 -0
- package/skills/backend-patterns/SKILL.md +586 -0
- package/skills/backend-patterns/catalyst-patterns.md +128 -0
- package/skills/bigquery-patterns/SKILL.md +27 -0
- package/skills/bigquery-patterns/performance-optimization.md +518 -0
- package/skills/bigquery-patterns/query-patterns.md +372 -0
- package/skills/bigquery-patterns/schema-design.md +78 -0
- package/skills/cloudstream-project-template/SKILL.md +20 -0
- package/skills/cloudstream-project-template/structure.md +65 -0
- package/skills/coding-standards/SKILL.md +524 -0
- package/skills/coding-standards/deluge-standards.md +83 -0
- package/skills/compliance-patterns/SKILL.md +28 -0
- package/skills/compliance-patterns/hipaa/audit-requirements.md +251 -0
- package/skills/compliance-patterns/hipaa/baa-process.md +298 -0
- package/skills/compliance-patterns/hipaa/data-archival-strategy.md +387 -0
- package/skills/compliance-patterns/hipaa/phi-handling.md +52 -0
- package/skills/compliance-patterns/pci-dss/saq-a-requirements.md +307 -0
- package/skills/compliance-patterns/pci-dss/tokenization-patterns.md +382 -0
- package/skills/compliance-patterns/pci-dss/zoho-checkout-patterns.md +56 -0
- package/skills/compliance-patterns/soc2/access-controls.md +344 -0
- package/skills/compliance-patterns/soc2/audit-logging.md +458 -0
- package/skills/compliance-patterns/soc2/change-management.md +403 -0
- package/skills/compliance-patterns/soc2/deluge-execution-logging.md +407 -0
- package/skills/consultancy-workflows/SKILL.md +19 -0
- package/skills/consultancy-workflows/client-isolation.md +21 -0
- package/skills/consultancy-workflows/documentation-automation.md +454 -0
- package/skills/consultancy-workflows/handoff-procedures.md +257 -0
- package/skills/consultancy-workflows/knowledge-capture.md +513 -0
- package/skills/consultancy-workflows/time-tracking.md +26 -0
- package/skills/continuous-learning/SKILL.md +84 -0
- package/skills/continuous-learning/config.json +18 -0
- package/skills/continuous-learning/evaluate-session.sh +60 -0
- package/skills/continuous-learning-v2/SKILL.md +126 -0
- package/skills/continuous-learning-v2/config.json +61 -0
- package/skills/frontend-patterns/SKILL.md +635 -0
- package/skills/frontend-patterns/zoho-widget-patterns.md +103 -0
- package/skills/gcp-data-engineering/SKILL.md +36 -0
- package/skills/gcp-data-engineering/bigquery/performance-optimization.md +337 -0
- package/skills/gcp-data-engineering/dataflow/error-handling.md +496 -0
- package/skills/gcp-data-engineering/dataflow/pipeline-patterns.md +444 -0
- package/skills/gcp-data-engineering/dbt/model-organization.md +63 -0
- package/skills/gcp-data-engineering/dbt/testing-patterns.md +503 -0
- package/skills/gcp-data-engineering/medallion-architecture/bronze-layer.md +60 -0
- package/skills/gcp-data-engineering/medallion-architecture/gold-layer.md +311 -0
- package/skills/gcp-data-engineering/medallion-architecture/layer-transitions.md +517 -0
- package/skills/gcp-data-engineering/medallion-architecture/silver-layer.md +305 -0
- package/skills/gcp-data-engineering/zoho-to-gcp/data-extraction.md +543 -0
- package/skills/gcp-data-engineering/zoho-to-gcp/real-time-vs-batch.md +337 -0
- package/skills/security-review/SKILL.md +498 -0
- package/skills/security-review/compliance-checklist.md +53 -0
- package/skills/strategic-compact/SKILL.md +67 -0
- package/skills/tdd-workflow/SKILL.md +413 -0
- package/skills/tdd-workflow/zoho-testing.md +124 -0
- package/skills/tutorial/SKILL.md +249 -0
- package/skills/tutorial/docs/ACCESSIBILITY.md +169 -0
- package/skills/tutorial/lessons/00-philosophy-and-workflow.md +198 -0
- package/skills/tutorial/lessons/01-basics.md +81 -0
- package/skills/tutorial/lessons/02-training.md +86 -0
- package/skills/tutorial/lessons/03-commands.md +109 -0
- package/skills/tutorial/lessons/04-workflows.md +115 -0
- package/skills/tutorial/lessons/05-compliance.md +116 -0
- package/skills/tutorial/lessons/06-zoho.md +121 -0
- package/skills/tutorial/lessons/07-hooks-system.md +277 -0
- package/skills/tutorial/lessons/08-mcp-servers.md +316 -0
- package/skills/tutorial/lessons/09-client-management.md +215 -0
- package/skills/tutorial/lessons/10-testing-e2e.md +260 -0
- package/skills/tutorial/lessons/11-skills-deep-dive.md +272 -0
- package/skills/tutorial/lessons/12-rules-system.md +326 -0
- package/skills/tutorial/lessons/13-golden-standard-graduation.md +213 -0
- package/skills/tutorial/lessons/14-fork-setup-and-sync.md +312 -0
- package/skills/tutorial/lessons/15-living-examples-system.md +221 -0
- package/skills/tutorial/tracks/accelerated/README.md +134 -0
- package/skills/tutorial/tracks/accelerated/assessment/checkpoint-1.md +161 -0
- package/skills/tutorial/tracks/accelerated/assessment/checkpoint-2.md +175 -0
- package/skills/tutorial/tracks/accelerated/day-1-core-concepts.md +234 -0
- package/skills/tutorial/tracks/accelerated/day-2-essential-commands.md +270 -0
- package/skills/tutorial/tracks/accelerated/day-3-workflow-mastery.md +305 -0
- package/skills/tutorial/tracks/accelerated/day-4-compliance-zoho.md +304 -0
- package/skills/tutorial/tracks/accelerated/day-5-hooks-skills.md +344 -0
- package/skills/tutorial/tracks/accelerated/day-6-client-testing.md +386 -0
- package/skills/tutorial/tracks/accelerated/day-7-graduation.md +369 -0
- package/skills/zoho-patterns/CHANGELOG.md +108 -0
- package/skills/zoho-patterns/SKILL.md +446 -0
- package/skills/zoho-patterns/analytics/dashboard-patterns.md +352 -0
- package/skills/zoho-patterns/analytics/zoho-to-bigquery-pipeline.md +427 -0
- package/skills/zoho-patterns/catalyst/appsail-deployment.md +349 -0
- package/skills/zoho-patterns/catalyst/context-close-patterns.md +354 -0
- package/skills/zoho-patterns/catalyst/cron-batch-processing.md +374 -0
- package/skills/zoho-patterns/catalyst/function-patterns.md +439 -0
- package/skills/zoho-patterns/creator/form-design.md +304 -0
- package/skills/zoho-patterns/creator/publish-api-patterns.md +313 -0
- package/skills/zoho-patterns/creator/widget-integration.md +306 -0
- package/skills/zoho-patterns/creator/workflow-automation.md +253 -0
- package/skills/zoho-patterns/deluge/api-patterns.md +468 -0
- package/skills/zoho-patterns/deluge/batch-processing.md +403 -0
- package/skills/zoho-patterns/deluge/cross-app-integration.md +356 -0
- package/skills/zoho-patterns/deluge/error-handling.md +423 -0
- package/skills/zoho-patterns/deluge/syntax-reference.md +65 -0
- package/skills/zoho-patterns/integration/cors-proxy-architecture.md +426 -0
- package/skills/zoho-patterns/integration/crm-books-native-sync.md +277 -0
- package/skills/zoho-patterns/integration/oauth-token-management.md +461 -0
- 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
|
+
}
|
package/scripts/build.js
ADDED
|
@@ -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}`);
|