@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.
Files changed (189) 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/config/versions.json +63 -0
  17. package/dist/hooks/hooks.json +209 -0
  18. package/dist/index.js +47 -0
  19. package/dist/lib/asset-value.js +609 -0
  20. package/dist/lib/client-manager.js +300 -0
  21. package/dist/lib/command-matcher.js +242 -0
  22. package/dist/lib/cross-session-patterns.js +754 -0
  23. package/dist/lib/intent-classifier.js +1075 -0
  24. package/dist/lib/package-manager.js +374 -0
  25. package/dist/lib/recommendation-engine.js +597 -0
  26. package/dist/lib/session-memory.js +489 -0
  27. package/dist/lib/skill-effectiveness.js +486 -0
  28. package/dist/lib/skill-matcher.js +595 -0
  29. package/dist/lib/tutorial-metrics.js +242 -0
  30. package/dist/lib/tutorial-progress.js +209 -0
  31. package/dist/lib/tutorial-renderer.js +431 -0
  32. package/dist/lib/utils.js +380 -0
  33. package/dist/lib/verify-formatter.js +143 -0
  34. package/dist/lib/workflow-state.js +249 -0
  35. package/hooks/hooks.json +209 -0
  36. package/package.json +5 -1
  37. package/scripts/aggregate-sessions.js +290 -0
  38. package/scripts/branch-name-validator.js +291 -0
  39. package/scripts/build.js +101 -0
  40. package/scripts/commands/client-switch.js +231 -0
  41. package/scripts/deprecate-skill.js +610 -0
  42. package/scripts/diagnose.js +324 -0
  43. package/scripts/doc-freshness.js +168 -0
  44. package/scripts/generate-weekly-digest.js +393 -0
  45. package/scripts/health-check.js +270 -0
  46. package/scripts/hooks/credential-check.js +101 -0
  47. package/scripts/hooks/evaluate-session.js +81 -0
  48. package/scripts/hooks/pre-compact.js +66 -0
  49. package/scripts/hooks/prompt-analyzer.js +276 -0
  50. package/scripts/hooks/prompt-router.js +422 -0
  51. package/scripts/hooks/quality-gate-enforcer.js +371 -0
  52. package/scripts/hooks/session-end.js +156 -0
  53. package/scripts/hooks/session-start.js +195 -0
  54. package/scripts/hooks/skill-injector.js +333 -0
  55. package/scripts/hooks/suggest-compact.js +58 -0
  56. package/scripts/lib/asset-value.js +609 -0
  57. package/scripts/lib/client-manager.js +300 -0
  58. package/scripts/lib/command-matcher.js +242 -0
  59. package/scripts/lib/cross-session-patterns.js +754 -0
  60. package/scripts/lib/intent-classifier.js +1075 -0
  61. package/scripts/lib/package-manager.js +374 -0
  62. package/scripts/lib/recommendation-engine.js +597 -0
  63. package/scripts/lib/session-memory.js +489 -0
  64. package/scripts/lib/skill-effectiveness.js +486 -0
  65. package/scripts/lib/skill-matcher.js +595 -0
  66. package/scripts/lib/tutorial-metrics.js +242 -0
  67. package/scripts/lib/tutorial-progress.js +209 -0
  68. package/scripts/lib/tutorial-renderer.js +431 -0
  69. package/scripts/lib/utils.js +380 -0
  70. package/scripts/lib/verify-formatter.js +143 -0
  71. package/scripts/lib/workflow-state.js +249 -0
  72. package/scripts/onboard.js +363 -0
  73. package/scripts/quarterly-report.js +692 -0
  74. package/scripts/setup-package-manager.js +204 -0
  75. package/scripts/sync-upstream.js +391 -0
  76. package/scripts/test.js +108 -0
  77. package/scripts/tutorial-runner.js +351 -0
  78. package/scripts/validate-all.js +201 -0
  79. package/scripts/verifiers/agents.js +245 -0
  80. package/scripts/verifiers/config.js +186 -0
  81. package/scripts/verifiers/environment.js +123 -0
  82. package/scripts/verifiers/hooks.js +188 -0
  83. package/scripts/verifiers/index.js +38 -0
  84. package/scripts/verifiers/persistence.js +140 -0
  85. package/scripts/verifiers/plugin.js +215 -0
  86. package/scripts/verifiers/skills.js +209 -0
  87. package/scripts/verify-setup.js +164 -0
  88. package/skills/INDEX.md +157 -0
  89. package/skills/backend-patterns/SKILL.md +586 -0
  90. package/skills/backend-patterns/catalyst-patterns.md +128 -0
  91. package/skills/bigquery-patterns/SKILL.md +27 -0
  92. package/skills/bigquery-patterns/performance-optimization.md +518 -0
  93. package/skills/bigquery-patterns/query-patterns.md +372 -0
  94. package/skills/bigquery-patterns/schema-design.md +78 -0
  95. package/skills/cloudstream-project-template/SKILL.md +20 -0
  96. package/skills/cloudstream-project-template/structure.md +65 -0
  97. package/skills/coding-standards/SKILL.md +524 -0
  98. package/skills/coding-standards/deluge-standards.md +83 -0
  99. package/skills/compliance-patterns/SKILL.md +28 -0
  100. package/skills/compliance-patterns/hipaa/audit-requirements.md +251 -0
  101. package/skills/compliance-patterns/hipaa/baa-process.md +298 -0
  102. package/skills/compliance-patterns/hipaa/data-archival-strategy.md +387 -0
  103. package/skills/compliance-patterns/hipaa/phi-handling.md +52 -0
  104. package/skills/compliance-patterns/pci-dss/saq-a-requirements.md +307 -0
  105. package/skills/compliance-patterns/pci-dss/tokenization-patterns.md +382 -0
  106. package/skills/compliance-patterns/pci-dss/zoho-checkout-patterns.md +56 -0
  107. package/skills/compliance-patterns/soc2/access-controls.md +344 -0
  108. package/skills/compliance-patterns/soc2/audit-logging.md +458 -0
  109. package/skills/compliance-patterns/soc2/change-management.md +403 -0
  110. package/skills/compliance-patterns/soc2/deluge-execution-logging.md +407 -0
  111. package/skills/consultancy-workflows/SKILL.md +19 -0
  112. package/skills/consultancy-workflows/client-isolation.md +21 -0
  113. package/skills/consultancy-workflows/documentation-automation.md +454 -0
  114. package/skills/consultancy-workflows/handoff-procedures.md +257 -0
  115. package/skills/consultancy-workflows/knowledge-capture.md +513 -0
  116. package/skills/consultancy-workflows/time-tracking.md +26 -0
  117. package/skills/continuous-learning/SKILL.md +84 -0
  118. package/skills/continuous-learning/config.json +18 -0
  119. package/skills/continuous-learning/evaluate-session.sh +60 -0
  120. package/skills/continuous-learning-v2/SKILL.md +126 -0
  121. package/skills/continuous-learning-v2/config.json +61 -0
  122. package/skills/frontend-patterns/SKILL.md +635 -0
  123. package/skills/frontend-patterns/zoho-widget-patterns.md +103 -0
  124. package/skills/gcp-data-engineering/SKILL.md +36 -0
  125. package/skills/gcp-data-engineering/bigquery/performance-optimization.md +337 -0
  126. package/skills/gcp-data-engineering/dataflow/error-handling.md +496 -0
  127. package/skills/gcp-data-engineering/dataflow/pipeline-patterns.md +444 -0
  128. package/skills/gcp-data-engineering/dbt/model-organization.md +63 -0
  129. package/skills/gcp-data-engineering/dbt/testing-patterns.md +503 -0
  130. package/skills/gcp-data-engineering/medallion-architecture/bronze-layer.md +60 -0
  131. package/skills/gcp-data-engineering/medallion-architecture/gold-layer.md +311 -0
  132. package/skills/gcp-data-engineering/medallion-architecture/layer-transitions.md +517 -0
  133. package/skills/gcp-data-engineering/medallion-architecture/silver-layer.md +305 -0
  134. package/skills/gcp-data-engineering/zoho-to-gcp/data-extraction.md +543 -0
  135. package/skills/gcp-data-engineering/zoho-to-gcp/real-time-vs-batch.md +337 -0
  136. package/skills/security-review/SKILL.md +498 -0
  137. package/skills/security-review/compliance-checklist.md +53 -0
  138. package/skills/strategic-compact/SKILL.md +67 -0
  139. package/skills/tdd-workflow/SKILL.md +413 -0
  140. package/skills/tdd-workflow/zoho-testing.md +124 -0
  141. package/skills/tutorial/SKILL.md +249 -0
  142. package/skills/tutorial/docs/ACCESSIBILITY.md +169 -0
  143. package/skills/tutorial/lessons/00-philosophy-and-workflow.md +198 -0
  144. package/skills/tutorial/lessons/01-basics.md +81 -0
  145. package/skills/tutorial/lessons/02-training.md +86 -0
  146. package/skills/tutorial/lessons/03-commands.md +109 -0
  147. package/skills/tutorial/lessons/04-workflows.md +115 -0
  148. package/skills/tutorial/lessons/05-compliance.md +116 -0
  149. package/skills/tutorial/lessons/06-zoho.md +121 -0
  150. package/skills/tutorial/lessons/07-hooks-system.md +277 -0
  151. package/skills/tutorial/lessons/08-mcp-servers.md +316 -0
  152. package/skills/tutorial/lessons/09-client-management.md +215 -0
  153. package/skills/tutorial/lessons/10-testing-e2e.md +260 -0
  154. package/skills/tutorial/lessons/11-skills-deep-dive.md +272 -0
  155. package/skills/tutorial/lessons/12-rules-system.md +326 -0
  156. package/skills/tutorial/lessons/13-golden-standard-graduation.md +213 -0
  157. package/skills/tutorial/lessons/14-fork-setup-and-sync.md +312 -0
  158. package/skills/tutorial/lessons/15-living-examples-system.md +221 -0
  159. package/skills/tutorial/tracks/accelerated/README.md +134 -0
  160. package/skills/tutorial/tracks/accelerated/assessment/checkpoint-1.md +161 -0
  161. package/skills/tutorial/tracks/accelerated/assessment/checkpoint-2.md +175 -0
  162. package/skills/tutorial/tracks/accelerated/day-1-core-concepts.md +234 -0
  163. package/skills/tutorial/tracks/accelerated/day-2-essential-commands.md +270 -0
  164. package/skills/tutorial/tracks/accelerated/day-3-workflow-mastery.md +305 -0
  165. package/skills/tutorial/tracks/accelerated/day-4-compliance-zoho.md +304 -0
  166. package/skills/tutorial/tracks/accelerated/day-5-hooks-skills.md +344 -0
  167. package/skills/tutorial/tracks/accelerated/day-6-client-testing.md +386 -0
  168. package/skills/tutorial/tracks/accelerated/day-7-graduation.md +369 -0
  169. package/skills/zoho-patterns/CHANGELOG.md +108 -0
  170. package/skills/zoho-patterns/SKILL.md +446 -0
  171. package/skills/zoho-patterns/analytics/dashboard-patterns.md +352 -0
  172. package/skills/zoho-patterns/analytics/zoho-to-bigquery-pipeline.md +427 -0
  173. package/skills/zoho-patterns/catalyst/appsail-deployment.md +349 -0
  174. package/skills/zoho-patterns/catalyst/context-close-patterns.md +354 -0
  175. package/skills/zoho-patterns/catalyst/cron-batch-processing.md +374 -0
  176. package/skills/zoho-patterns/catalyst/function-patterns.md +439 -0
  177. package/skills/zoho-patterns/creator/form-design.md +304 -0
  178. package/skills/zoho-patterns/creator/publish-api-patterns.md +313 -0
  179. package/skills/zoho-patterns/creator/widget-integration.md +306 -0
  180. package/skills/zoho-patterns/creator/workflow-automation.md +253 -0
  181. package/skills/zoho-patterns/deluge/api-patterns.md +468 -0
  182. package/skills/zoho-patterns/deluge/batch-processing.md +403 -0
  183. package/skills/zoho-patterns/deluge/cross-app-integration.md +356 -0
  184. package/skills/zoho-patterns/deluge/error-handling.md +423 -0
  185. package/skills/zoho-patterns/deluge/syntax-reference.md +65 -0
  186. package/skills/zoho-patterns/integration/cors-proxy-architecture.md +426 -0
  187. package/skills/zoho-patterns/integration/crm-books-native-sync.md +277 -0
  188. package/skills/zoho-patterns/integration/oauth-token-management.md +461 -0
  189. package/skills/zoho-patterns/integration/zoho-flow-patterns.md +334 -0
@@ -0,0 +1,351 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Tutorial Runner - Visual Interactive Tutorial for Everything Claude Code
4
+ *
5
+ * Usage:
6
+ * node scripts/tutorial-runner.js # Show status and current lesson
7
+ * node scripts/tutorial-runner.js <lesson> # Go to specific lesson (0-14)
8
+ * node scripts/tutorial-runner.js status # Show progress status
9
+ * node scripts/tutorial-runner.js reset # Reset all progress
10
+ * node scripts/tutorial-runner.js complete <num> # Mark lesson as complete
11
+ * node scripts/tutorial-runner.js certificate # Show completion certificate
12
+ * node scripts/tutorial-runner.js stats # Show usage statistics
13
+ * node scripts/tutorial-runner.js --accessible # Disable colors for accessibility
14
+ */
15
+
16
+ const path = require('path');
17
+ const fs = require('fs');
18
+ const progress = require('./lib/tutorial-progress');
19
+ const renderer = require('./lib/tutorial-renderer');
20
+ const metrics = require('./lib/tutorial-metrics');
21
+
22
+ // Lessons directory
23
+ const LESSONS_DIR = path.join(__dirname, '..', 'skills', 'tutorial', 'lessons');
24
+
25
+ /**
26
+ * Generate a unique certificate ID.
27
+ * @returns {string} Certificate ID
28
+ */
29
+ function generateCertificateId() {
30
+ const date = new Date();
31
+ const year = date.getFullYear();
32
+ const random = Math.random().toString(36).substring(2, 6).toUpperCase();
33
+ return `ECC-${year}-${random}`;
34
+ }
35
+
36
+ /**
37
+ * Load lesson content from file.
38
+ * @param {number} lessonNum - Lesson number
39
+ * @returns {string|null} Lesson content or null
40
+ */
41
+ function loadLessonContent(lessonNum) {
42
+ const lesson = progress.getLessonInfo(lessonNum);
43
+ if (!lesson) return null;
44
+
45
+ const filePath = path.join(LESSONS_DIR, lesson.file);
46
+ if (!fs.existsSync(filePath)) return null;
47
+
48
+ return fs.readFileSync(filePath, 'utf8');
49
+ }
50
+
51
+ /**
52
+ * Extract commands from lesson content.
53
+ * @param {string} content - Lesson markdown content
54
+ * @returns {Array<string>} Array of command names
55
+ */
56
+ function extractCommands(content) {
57
+ const commands = [];
58
+ const regex = /\/(\w+[-\w]*)/g;
59
+ let match;
60
+ while ((match = regex.exec(content)) !== null) {
61
+ const cmd = `/${match[1]}`;
62
+ if (!commands.includes(cmd)) {
63
+ commands.push(cmd);
64
+ }
65
+ }
66
+ return commands.slice(0, 5); // Limit to 5 for display
67
+ }
68
+
69
+ /**
70
+ * Show tutorial status.
71
+ */
72
+ async function showStatus() {
73
+ await renderer.init();
74
+
75
+ const state = progress.loadProgress();
76
+
77
+ console.log('');
78
+ console.log(renderer.renderBanner());
79
+ console.log('');
80
+ console.log(renderer.renderProgressBar(state.completedLessons.length, progress.TOTAL_LESSONS));
81
+ console.log('');
82
+ console.log(renderer.renderLessonList(state, progress.LESSONS));
83
+ console.log('');
84
+
85
+ if (progress.isComplete(state)) {
86
+ console.log(renderer.renderSuccess('Tutorial complete!'));
87
+ console.log(' Terminal: node scripts/tutorial-runner.js certificate');
88
+ console.log(' Claude Code: /tutorial certificate');
89
+ } else {
90
+ console.log('Next lesson:');
91
+ console.log(` Terminal: node scripts/tutorial-runner.js ${state.currentLesson}`);
92
+ console.log(` Claude Code: /tutorial ${state.currentLesson}`);
93
+ }
94
+ console.log('');
95
+ }
96
+
97
+ /**
98
+ * Show a specific lesson.
99
+ * @param {number} lessonNum - Lesson number
100
+ */
101
+ async function showLesson(lessonNum) {
102
+ await renderer.init();
103
+
104
+ const lesson = progress.getLessonInfo(lessonNum);
105
+ if (!lesson) {
106
+ console.error(
107
+ renderer.renderError(
108
+ `Invalid lesson number: ${lessonNum}. Valid: 0-${progress.TOTAL_LESSONS - 1}`
109
+ )
110
+ );
111
+ process.exit(1);
112
+ }
113
+
114
+ // Record metrics
115
+ metrics.recordLessonStart(lessonNum);
116
+
117
+ const state = progress.setCurrentLesson(lessonNum);
118
+
119
+ console.log('');
120
+ console.log(renderer.renderBanner());
121
+ console.log('');
122
+ console.log(renderer.renderProgressBar(state.completedLessons.length, progress.TOTAL_LESSONS));
123
+ console.log('');
124
+ console.log(renderer.renderLessonHeader(lesson));
125
+ console.log('');
126
+
127
+ const content = loadLessonContent(lessonNum);
128
+ if (content) {
129
+ // Output styled lesson content
130
+ console.log(renderer.renderLessonContent(content));
131
+ } else {
132
+ console.log(`Lesson file not found: ${lesson.file}`);
133
+ }
134
+
135
+ console.log('');
136
+ console.log('To mark complete:');
137
+ console.log(` Terminal: node scripts/tutorial-runner.js complete ${lessonNum}`);
138
+ console.log(' Claude Code: (automatic when exercise completed)');
139
+ console.log('');
140
+ }
141
+
142
+ /**
143
+ * Mark a lesson as complete.
144
+ * @param {number} lessonNum - Lesson number
145
+ */
146
+ async function completeLesson(lessonNum) {
147
+ await renderer.init();
148
+
149
+ const lesson = progress.getLessonInfo(lessonNum);
150
+ if (!lesson) {
151
+ console.error(renderer.renderError(`Invalid lesson number: ${lessonNum}`));
152
+ process.exit(1);
153
+ }
154
+
155
+ // Record metrics
156
+ metrics.recordLessonEnd(lessonNum);
157
+
158
+ const state = progress.completeLesson(lessonNum);
159
+
160
+ const content = loadLessonContent(lessonNum);
161
+ const commands = content ? extractCommands(content) : [];
162
+
163
+ const nextLesson = lessonNum < progress.TOTAL_LESSONS ? lessonNum + 1 : null;
164
+
165
+ console.log('');
166
+ console.log(renderer.renderCompletionBadge(lesson, commands, nextLesson));
167
+ console.log('');
168
+
169
+ if (progress.isComplete(state)) {
170
+ metrics.markComplete();
171
+ console.log(renderer.renderSuccess('Congratulations! You completed all lessons!'));
172
+ console.log('Get your certificate:');
173
+ console.log(' Terminal: node scripts/tutorial-runner.js certificate');
174
+ console.log(' Claude Code: /tutorial certificate');
175
+ }
176
+ console.log('');
177
+ }
178
+
179
+ /**
180
+ * Reset all progress.
181
+ */
182
+ async function resetProgress() {
183
+ await renderer.init();
184
+
185
+ progress.resetProgress();
186
+ console.log('');
187
+ console.log(renderer.renderSuccess('Tutorial progress has been reset.'));
188
+ console.log('Start from beginning:');
189
+ console.log(' Terminal: node scripts/tutorial-runner.js 0');
190
+ console.log(' Claude Code: /tutorial 0');
191
+ console.log('');
192
+ }
193
+
194
+ /**
195
+ * Show completion certificate.
196
+ */
197
+ async function showCertificate() {
198
+ await renderer.init();
199
+
200
+ const state = progress.loadProgress();
201
+
202
+ if (!progress.isComplete(state)) {
203
+ console.error(renderer.renderError('Tutorial not complete. Complete all 15 lessons first.'));
204
+ console.log('');
205
+ console.log(renderer.renderProgressBar(state.completedLessons.length, progress.TOTAL_LESSONS));
206
+ console.log('');
207
+ process.exit(1);
208
+ }
209
+
210
+ const certId = generateCertificateId();
211
+
212
+ console.log('');
213
+ console.log(renderer.renderCertificate(state, certId));
214
+ console.log('');
215
+ }
216
+
217
+ /**
218
+ * Show resume prompt (for session-start hook).
219
+ */
220
+ async function showResumePrompt() {
221
+ await renderer.init();
222
+
223
+ if (!progress.hasProgress()) {
224
+ return; // No progress to show
225
+ }
226
+
227
+ const state = progress.loadProgress();
228
+
229
+ if (progress.isComplete(state)) {
230
+ return; // Already complete
231
+ }
232
+
233
+ console.log('');
234
+ console.log(renderer.renderResumePrompt(state));
235
+ console.log('');
236
+ }
237
+
238
+ /**
239
+ * Show usage statistics.
240
+ */
241
+ async function showStats() {
242
+ await renderer.init();
243
+
244
+ if (!metrics.hasMetrics()) {
245
+ console.log('');
246
+ console.log('No metrics data yet. Start a lesson to begin tracking.');
247
+ console.log('');
248
+ return;
249
+ }
250
+
251
+ const stats = metrics.getStats();
252
+
253
+ console.log('');
254
+ console.log('Tutorial Statistics:');
255
+ console.log('');
256
+ console.log(` Total time: ${stats.totalTime}`);
257
+ console.log(` Sessions: ${stats.totalSessions}`);
258
+ console.log(` Lessons visited: ${stats.lessonsVisited}/${progress.TOTAL_LESSONS}`);
259
+
260
+ if (stats.mostVisited) {
261
+ const lessonInfo = progress.getLessonInfo(stats.mostVisited);
262
+ console.log(
263
+ ` Most visited: Lesson ${stats.mostVisited}: ${lessonInfo.title} (${stats.mostVisitedCount} visits)`
264
+ );
265
+ }
266
+
267
+ console.log(` Avg per lesson: ${stats.averageTimePerLesson}`);
268
+ console.log('');
269
+
270
+ if (stats.completedAt) {
271
+ const completedDate = new Date(stats.completedAt).toLocaleDateString();
272
+ console.log(` Completed: ${completedDate}`);
273
+ console.log('');
274
+ }
275
+
276
+ // Show per-lesson breakdown if there's data
277
+ if (Object.keys(stats.lessonMetrics).length > 0) {
278
+ console.log(' Per-lesson breakdown:');
279
+ for (const [lessonNum, data] of Object.entries(stats.lessonMetrics)) {
280
+ const lessonInfo = progress.getLessonInfo(parseInt(lessonNum, 10));
281
+ const timeStr = metrics.formatTime(data.totalTimeMs);
282
+ console.log(` Lesson ${lessonNum}: ${data.visits} visit(s), ${timeStr}`);
283
+ }
284
+ console.log('');
285
+ }
286
+ }
287
+
288
+ /**
289
+ * Main entry point.
290
+ */
291
+ async function main() {
292
+ const args = process.argv.slice(2).filter((a) => !a.startsWith('--'));
293
+
294
+ if (args.length === 0) {
295
+ await showStatus();
296
+ return;
297
+ }
298
+
299
+ const command = args[0].toLowerCase();
300
+
301
+ switch (command) {
302
+ case 'status':
303
+ await showStatus();
304
+ break;
305
+
306
+ case 'reset':
307
+ await resetProgress();
308
+ break;
309
+
310
+ case 'certificate':
311
+ case 'cert':
312
+ await showCertificate();
313
+ break;
314
+
315
+ case 'complete':
316
+ if (!args[1]) {
317
+ console.error('Usage: node scripts/tutorial-runner.js complete <lesson-number>');
318
+ process.exit(1);
319
+ }
320
+ await completeLesson(parseInt(args[1], 10));
321
+ break;
322
+
323
+ case 'resume':
324
+ await showResumePrompt();
325
+ break;
326
+
327
+ case 'stats':
328
+ case 'metrics':
329
+ await showStats();
330
+ break;
331
+
332
+ default: {
333
+ // Assume it's a lesson number
334
+ const lessonNum = parseInt(command, 10);
335
+ if (isNaN(lessonNum) || lessonNum < 0 || lessonNum >= progress.TOTAL_LESSONS) {
336
+ console.error(`Invalid command or lesson number: ${command}`);
337
+ console.error(`Valid lessons: 0-${progress.TOTAL_LESSONS - 1}`);
338
+ console.error('Commands: status, reset, complete <n>, certificate, stats');
339
+ process.exit(1);
340
+ }
341
+ await showLesson(lessonNum);
342
+ break;
343
+ }
344
+ }
345
+ }
346
+
347
+ // Run
348
+ main().catch((err) => {
349
+ console.error('Error:', err.message);
350
+ process.exit(1);
351
+ });
@@ -0,0 +1,201 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Master Validation Orchestrator
4
+ * Runs all validation phases in sequence with proper error handling.
5
+ */
6
+ const { spawn } = require('child_process');
7
+ const path = require('path');
8
+
9
+ const ROOT = path.join(__dirname, '..');
10
+
11
+ // Parse arguments
12
+ const args = process.argv.slice(2);
13
+ const quickMode = args.includes('--quick');
14
+ const verbose = args.includes('--verbose');
15
+ const continueOnError = args.includes('--continue');
16
+
17
+ // ANSI colors
18
+ const colors = {
19
+ reset: '\x1b[0m',
20
+ green: '\x1b[32m',
21
+ red: '\x1b[31m',
22
+ yellow: '\x1b[33m',
23
+ blue: '\x1b[34m',
24
+ dim: '\x1b[2m',
25
+ };
26
+
27
+ function log(message, color = 'reset') {
28
+ console.log(`${colors[color]}${message}${colors.reset}`);
29
+ }
30
+
31
+ function header(message) {
32
+ console.log('\n' + '='.repeat(60));
33
+ log(message, 'blue');
34
+ console.log('='.repeat(60));
35
+ }
36
+
37
+ /**
38
+ * Run a command and return a promise
39
+ */
40
+ function runCommand(command, args = [], options = {}) {
41
+ return new Promise((resolve, reject) => {
42
+ const startTime = Date.now();
43
+ const proc = spawn(command, args, {
44
+ cwd: ROOT,
45
+ stdio: verbose ? 'inherit' : 'pipe',
46
+ shell: true,
47
+ ...options,
48
+ });
49
+
50
+ let stdout = '';
51
+ let stderr = '';
52
+
53
+ if (!verbose && proc.stdout) {
54
+ proc.stdout.on('data', (data) => {
55
+ stdout += data.toString();
56
+ });
57
+ }
58
+
59
+ if (!verbose && proc.stderr) {
60
+ proc.stderr.on('data', (data) => {
61
+ stderr += data.toString();
62
+ });
63
+ }
64
+
65
+ proc.on('close', (code) => {
66
+ const duration = ((Date.now() - startTime) / 1000).toFixed(1);
67
+ if (code === 0) {
68
+ resolve({ success: true, duration, stdout, stderr });
69
+ } else {
70
+ reject({ success: false, code, duration, stdout, stderr });
71
+ }
72
+ });
73
+
74
+ proc.on('error', (err) => {
75
+ reject({ success: false, error: err.message, stdout, stderr });
76
+ });
77
+ });
78
+ }
79
+
80
+ /**
81
+ * Validation phases
82
+ */
83
+ const phases = [
84
+ {
85
+ name: 'Environment Check',
86
+ command: 'npm',
87
+ args: ['run', 'verify:quick'],
88
+ required: true,
89
+ quick: true,
90
+ },
91
+ {
92
+ name: 'Plugin Structure Validation',
93
+ command: 'npm',
94
+ args: ['run', 'validate'],
95
+ required: true,
96
+ quick: true,
97
+ },
98
+ {
99
+ name: 'Full Test Suite',
100
+ command: 'npm',
101
+ args: ['test'],
102
+ required: true,
103
+ quick: false,
104
+ },
105
+ {
106
+ name: 'ESLint Check',
107
+ command: 'npm',
108
+ args: ['run', 'lint'],
109
+ required: true,
110
+ quick: false,
111
+ },
112
+ {
113
+ name: 'Prettier Format Check',
114
+ command: 'npm',
115
+ args: ['run', 'format'],
116
+ required: true,
117
+ quick: false,
118
+ },
119
+ {
120
+ name: 'Markdown Link Validation',
121
+ command: 'node',
122
+ args: ['tests/structure/links.test.js'],
123
+ required: true,
124
+ quick: false,
125
+ },
126
+ {
127
+ name: 'Documentation Freshness',
128
+ command: 'node',
129
+ args: ['scripts/doc-freshness.js'],
130
+ required: false,
131
+ quick: false,
132
+ },
133
+ ];
134
+
135
+ async function main() {
136
+ log('\n\u2728 CloudStream Claude Code - Enterprise Validation\n', 'blue');
137
+ log(`Mode: ${quickMode ? 'Quick' : 'Full'}`, 'dim');
138
+ log(`Continue on error: ${continueOnError ? 'Yes' : 'No'}`, 'dim');
139
+
140
+ const results = [];
141
+ let hasFailure = false;
142
+
143
+ for (const phase of phases) {
144
+ // Skip non-quick phases in quick mode
145
+ if (quickMode && !phase.quick) {
146
+ continue;
147
+ }
148
+
149
+ header(`Phase: ${phase.name}`);
150
+
151
+ try {
152
+ const result = await runCommand(phase.command, phase.args);
153
+ log(`\u2713 ${phase.name} passed (${result.duration}s)`, 'green');
154
+ results.push({ phase: phase.name, success: true, duration: result.duration });
155
+ } catch (err) {
156
+ log(`\u2717 ${phase.name} failed`, 'red');
157
+ if (!verbose && err.stderr) {
158
+ console.log(colors.dim + err.stderr.slice(0, 500) + colors.reset);
159
+ }
160
+ results.push({ phase: phase.name, success: false, duration: err.duration });
161
+
162
+ if (phase.required) {
163
+ hasFailure = true;
164
+ if (!continueOnError) {
165
+ break;
166
+ }
167
+ }
168
+ }
169
+ }
170
+
171
+ // Summary
172
+ header('Validation Summary');
173
+
174
+ const passed = results.filter((r) => r.success).length;
175
+ const failed = results.filter((r) => !r.success).length;
176
+ const totalTime = results.reduce((sum, r) => sum + parseFloat(r.duration || 0), 0).toFixed(1);
177
+
178
+ for (const result of results) {
179
+ const icon = result.success ? '\u2713' : '\u2717';
180
+ const color = result.success ? 'green' : 'red';
181
+ log(` ${icon} ${result.phase} (${result.duration}s)`, color);
182
+ }
183
+
184
+ console.log('\n' + '-'.repeat(40));
185
+ log(`Passed: ${passed}`, 'green');
186
+ if (failed > 0) log(`Failed: ${failed}`, 'red');
187
+ log(`Total time: ${totalTime}s`, 'dim');
188
+
189
+ if (hasFailure) {
190
+ log('\n\u2717 Validation FAILED', 'red');
191
+ process.exit(1);
192
+ } else {
193
+ log('\n\u2713 All validations PASSED', 'green');
194
+ process.exit(0);
195
+ }
196
+ }
197
+
198
+ main().catch((err) => {
199
+ console.error('Unexpected error:', err);
200
+ process.exit(1);
201
+ });