@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,245 @@
1
+ /**
2
+ * Agents Verifier - Dynamic agent validation using versions.json as source of truth
3
+ */
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const { createCheck, createResult, SEVERITY } = require('../lib/verify-formatter');
8
+ const { getPluginRoot } = require('./plugin');
9
+
10
+ const NAME = 'Agents';
11
+
12
+ /**
13
+ * Load versions.json registry
14
+ */
15
+ function loadRegistry() {
16
+ const pluginRoot = getPluginRoot();
17
+ const versionsPath = path.join(pluginRoot, 'config', 'versions.json');
18
+
19
+ try {
20
+ const content = fs.readFileSync(versionsPath, 'utf8');
21
+ return JSON.parse(content);
22
+ } catch {
23
+ return null;
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Get active agents from registry
29
+ */
30
+ function getRegisteredAgents(versions) {
31
+ if (!versions || !versions.agents) return [];
32
+
33
+ return Object.entries(versions.agents)
34
+ .filter(([, info]) => info.status === 'active')
35
+ .map(([name]) => name);
36
+ }
37
+
38
+ /**
39
+ * Get agents directory path
40
+ */
41
+ function getAgentsDir() {
42
+ const pluginRoot = getPluginRoot();
43
+
44
+ // Check multiple possible locations
45
+ const locations = [
46
+ path.join(pluginRoot, 'agents'),
47
+ path.join(pluginRoot, '..', 'agents'),
48
+ path.join(process.cwd(), 'agents'),
49
+ ];
50
+
51
+ for (const loc of locations) {
52
+ if (fs.existsSync(loc)) {
53
+ return loc;
54
+ }
55
+ }
56
+
57
+ return path.join(pluginRoot, 'agents');
58
+ }
59
+
60
+ /**
61
+ * Get existing agent files
62
+ */
63
+ function getExistingAgents() {
64
+ const agentsDir = getAgentsDir();
65
+
66
+ if (!fs.existsSync(agentsDir)) return [];
67
+
68
+ return fs
69
+ .readdirSync(agentsDir)
70
+ .filter((f) => f.endsWith('.md') && f !== 'INDEX.md')
71
+ .map((f) => f.replace('.md', ''));
72
+ }
73
+
74
+ /**
75
+ * Check registry vs disk bidirectionally
76
+ */
77
+ function checkRegistrySync() {
78
+ const versions = loadRegistry();
79
+ const checks = [];
80
+
81
+ if (!versions) {
82
+ return [
83
+ createCheck('Agents registry', false, {
84
+ severity: SEVERITY.WARNING,
85
+ message: 'cannot load versions.json',
86
+ remediation: 'Fix or create config/versions.json',
87
+ }),
88
+ ];
89
+ }
90
+
91
+ const registered = getRegisteredAgents(versions);
92
+ const existing = getExistingAgents();
93
+
94
+ // Check: All registered agents exist on disk
95
+ const missing = registered.filter((a) => !existing.includes(a));
96
+ if (missing.length > 0) {
97
+ checks.push(
98
+ createCheck('Registered agents exist', false, {
99
+ severity: SEVERITY.WARNING,
100
+ message: `missing: ${missing.slice(0, 3).join(', ')}${missing.length > 3 ? '...' : ''}`,
101
+ remediation: `Create missing agent files or update versions.json`,
102
+ })
103
+ );
104
+ } else {
105
+ checks.push(
106
+ createCheck('Registered agents exist', true, {
107
+ message: `${registered.length} verified`,
108
+ })
109
+ );
110
+ }
111
+
112
+ // Check: All existing agents are registered
113
+ const unregistered = existing.filter((a) => !registered.includes(a));
114
+ if (unregistered.length > 0) {
115
+ checks.push(
116
+ createCheck('Agents are registered', false, {
117
+ severity: SEVERITY.WARNING,
118
+ message: `unregistered: ${unregistered.slice(0, 3).join(', ')}${unregistered.length > 3 ? '...' : ''}`,
119
+ remediation: `Add agents to versions.json or remove files`,
120
+ })
121
+ );
122
+ } else {
123
+ checks.push(
124
+ createCheck('Agents are registered', true, {
125
+ message: `${existing.length} on disk`,
126
+ })
127
+ );
128
+ }
129
+
130
+ return checks;
131
+ }
132
+
133
+ /**
134
+ * Parse YAML frontmatter from markdown
135
+ */
136
+ function parseFrontmatter(content) {
137
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
138
+ if (!match) return null;
139
+
140
+ const frontmatter = {};
141
+ const lines = match[1].split('\n');
142
+
143
+ for (const line of lines) {
144
+ const colonIndex = line.indexOf(':');
145
+ if (colonIndex > 0) {
146
+ const key = line.slice(0, colonIndex).trim();
147
+ const value = line.slice(colonIndex + 1).trim();
148
+ frontmatter[key] = value;
149
+ }
150
+ }
151
+
152
+ return frontmatter;
153
+ }
154
+
155
+ /**
156
+ * Check agents have valid frontmatter
157
+ */
158
+ function checkAgentFrontmatter() {
159
+ const agentsDir = getAgentsDir();
160
+ const checks = [];
161
+
162
+ if (!fs.existsSync(agentsDir)) {
163
+ return [
164
+ createCheck('Agent frontmatter', false, {
165
+ severity: SEVERITY.WARNING,
166
+ message: 'agents/ directory not found',
167
+ }),
168
+ ];
169
+ }
170
+
171
+ const agentFiles = fs.readdirSync(agentsDir).filter((f) => f.endsWith('.md') && f !== 'INDEX.md');
172
+
173
+ let validCount = 0;
174
+ let invalidAgents = [];
175
+
176
+ for (const file of agentFiles) {
177
+ const filePath = path.join(agentsDir, file);
178
+ try {
179
+ const content = fs.readFileSync(filePath, 'utf8');
180
+ const frontmatter = parseFrontmatter(content);
181
+
182
+ if (!frontmatter) {
183
+ invalidAgents.push({ file, reason: 'no frontmatter' });
184
+ } else if (!frontmatter.name) {
185
+ invalidAgents.push({ file, reason: 'missing name' });
186
+ } else if (!frontmatter.model) {
187
+ invalidAgents.push({ file, reason: 'missing model' });
188
+ } else {
189
+ validCount++;
190
+ }
191
+ } catch {
192
+ invalidAgents.push({ file, reason: 'read error' });
193
+ }
194
+ }
195
+
196
+ if (invalidAgents.length > 0) {
197
+ const examples = invalidAgents.slice(0, 2).map((a) => `${a.file} (${a.reason})`);
198
+ checks.push(
199
+ createCheck('Agent frontmatter', false, {
200
+ severity: SEVERITY.WARNING,
201
+ message: `${invalidAgents.length} invalid`,
202
+ remediation: `Fix: ${examples.join(', ')}${invalidAgents.length > 2 ? '...' : ''}`,
203
+ })
204
+ );
205
+ } else {
206
+ checks.push(
207
+ createCheck('Agent frontmatter', true, {
208
+ message: `${validCount} valid`,
209
+ })
210
+ );
211
+ }
212
+
213
+ return checks;
214
+ }
215
+
216
+ /**
217
+ * Check INDEX.md exists
218
+ */
219
+ function checkIndexFile() {
220
+ const agentsDir = getAgentsDir();
221
+ const indexPath = path.join(agentsDir, 'INDEX.md');
222
+
223
+ if (fs.existsSync(indexPath)) {
224
+ return createCheck('INDEX.md', true, {
225
+ message: 'found',
226
+ });
227
+ }
228
+
229
+ return createCheck('INDEX.md', false, {
230
+ severity: SEVERITY.WARNING,
231
+ message: 'not found',
232
+ remediation: 'Create agents/INDEX.md listing all agents',
233
+ });
234
+ }
235
+
236
+ /**
237
+ * Run all agents checks
238
+ */
239
+ function verify() {
240
+ const checks = [...checkRegistrySync(), ...checkAgentFrontmatter(), checkIndexFile()];
241
+
242
+ return createResult(NAME, checks);
243
+ }
244
+
245
+ module.exports = { verify, NAME };
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Config Verifier - JSON configuration file validation
3
+ */
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const { createCheck, createResult, SEVERITY } = require('../lib/verify-formatter');
8
+ const { getPluginRoot } = require('./plugin');
9
+
10
+ const NAME = 'Config';
11
+
12
+ /**
13
+ * Check a JSON config file
14
+ */
15
+ function checkConfigFile(name, filePath, requiredFields = []) {
16
+ if (!fs.existsSync(filePath)) {
17
+ return createCheck(name, false, {
18
+ severity: SEVERITY.WARNING,
19
+ message: 'not found',
20
+ remediation: `Create ${name} configuration file`,
21
+ });
22
+ }
23
+
24
+ try {
25
+ const content = fs.readFileSync(filePath, 'utf8');
26
+ const config = JSON.parse(content);
27
+
28
+ // Check required fields
29
+ const missingFields = requiredFields.filter((field) => !config[field]);
30
+ if (missingFields.length > 0) {
31
+ return createCheck(name, false, {
32
+ severity: SEVERITY.WARNING,
33
+ message: `missing: ${missingFields.join(', ')}`,
34
+ remediation: `Add missing fields to ${name}`,
35
+ });
36
+ }
37
+
38
+ return createCheck(name, true, {
39
+ message: 'valid',
40
+ });
41
+ } catch (err) {
42
+ return createCheck(name, false, {
43
+ severity: SEVERITY.CRITICAL,
44
+ message: 'JSON parse error',
45
+ remediation: `Fix JSON syntax in ${name}`,
46
+ });
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Check versions.json (critical - source of truth)
52
+ */
53
+ function checkVersionsJson() {
54
+ const pluginRoot = getPluginRoot();
55
+ const configPath = path.join(pluginRoot, 'config', 'versions.json');
56
+
57
+ const check = checkConfigFile('versions.json', configPath, ['skills', 'agents']);
58
+
59
+ if (check.passed) {
60
+ try {
61
+ const content = fs.readFileSync(configPath, 'utf8');
62
+ const config = JSON.parse(content);
63
+ const skillCount = Object.keys(config.skills || {}).length;
64
+ const agentCount = Object.keys(config.agents || {}).length;
65
+ check.message = `${skillCount} skills, ${agentCount} agents`;
66
+ } catch {
67
+ // Already handled
68
+ }
69
+ } else {
70
+ check.severity = SEVERITY.CRITICAL;
71
+ }
72
+
73
+ return check;
74
+ }
75
+
76
+ /**
77
+ * Check quality-gates.json
78
+ */
79
+ function checkQualityGatesJson() {
80
+ const pluginRoot = getPluginRoot();
81
+ const configPath = path.join(pluginRoot, 'config', 'quality-gates.json');
82
+
83
+ const check = checkConfigFile('quality-gates.json', configPath, ['gates']);
84
+
85
+ if (check.passed) {
86
+ try {
87
+ const content = fs.readFileSync(configPath, 'utf8');
88
+ const config = JSON.parse(content);
89
+ const gateCount = Object.keys(config.gates || {}).length;
90
+ check.message = `${gateCount} gates defined`;
91
+ } catch {
92
+ // Already handled
93
+ }
94
+ }
95
+
96
+ return check;
97
+ }
98
+
99
+ /**
100
+ * Check for .env in repo root (should not exist)
101
+ */
102
+ function checkNoEnvInRepo() {
103
+ const pluginRoot = getPluginRoot();
104
+ // Check both plugin root and parent
105
+ const envLocations = [
106
+ path.join(pluginRoot, '.env'),
107
+ path.join(pluginRoot, '..', '.env'),
108
+ path.join(pluginRoot, '.env.local'),
109
+ path.join(pluginRoot, '..', '.env.local'),
110
+ ];
111
+
112
+ for (const envPath of envLocations) {
113
+ if (fs.existsSync(envPath)) {
114
+ return createCheck('No .env in repo', false, {
115
+ severity: SEVERITY.CRITICAL,
116
+ message: 'found .env file',
117
+ remediation: 'Remove .env from repo and add to .gitignore',
118
+ });
119
+ }
120
+ }
121
+
122
+ return createCheck('No .env in repo', true, {
123
+ message: 'clean',
124
+ });
125
+ }
126
+
127
+ /**
128
+ * Check other config files
129
+ */
130
+ function checkOtherConfigs() {
131
+ const pluginRoot = getPluginRoot();
132
+ const configDir = path.join(pluginRoot, 'config');
133
+ const checks = [];
134
+
135
+ const optionalConfigs = [
136
+ 'aggregation.json',
137
+ 'asset-value.json',
138
+ 'onboarding-milestones.json',
139
+ 'prompt-router.json',
140
+ 'shared-knowledge.json',
141
+ ];
142
+
143
+ if (!fs.existsSync(configDir)) {
144
+ return [
145
+ createCheck('config/ directory', false, {
146
+ severity: SEVERITY.WARNING,
147
+ message: 'not found',
148
+ }),
149
+ ];
150
+ }
151
+
152
+ for (const configName of optionalConfigs) {
153
+ const configPath = path.join(configDir, configName);
154
+ if (fs.existsSync(configPath)) {
155
+ const check = checkConfigFile(configName, configPath);
156
+ checks.push(check);
157
+ }
158
+ }
159
+
160
+ // Summary if no optional configs checked
161
+ if (checks.length === 0) {
162
+ checks.push(
163
+ createCheck('Optional configs', true, {
164
+ message: 'none present (ok)',
165
+ })
166
+ );
167
+ }
168
+
169
+ return checks;
170
+ }
171
+
172
+ /**
173
+ * Run all config checks
174
+ */
175
+ function verify() {
176
+ const checks = [
177
+ checkVersionsJson(),
178
+ checkQualityGatesJson(),
179
+ checkNoEnvInRepo(),
180
+ ...checkOtherConfigs(),
181
+ ];
182
+
183
+ return createResult(NAME, checks);
184
+ }
185
+
186
+ module.exports = { verify, NAME };
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Environment Verifier - System prerequisites check
3
+ */
4
+
5
+ const { execSync } = require('child_process');
6
+ const { createCheck, createResult, SEVERITY } = require('../lib/verify-formatter');
7
+ const { commandExists } = require('../lib/utils');
8
+
9
+ const NAME = 'Environment';
10
+
11
+ /**
12
+ * Check Node.js version (requires >= 18)
13
+ */
14
+ function checkNodeVersion() {
15
+ const version = process.versions.node;
16
+ const major = parseInt(version.split('.')[0], 10);
17
+ const passed = major >= 18;
18
+
19
+ return createCheck('Node.js', passed, {
20
+ message: `v${version}`,
21
+ severity: passed ? SEVERITY.INFO : SEVERITY.CRITICAL,
22
+ remediation: 'Install Node.js 18+ from https://nodejs.org',
23
+ });
24
+ }
25
+
26
+ /**
27
+ * Check Git is installed
28
+ */
29
+ function checkGit() {
30
+ try {
31
+ const version = execSync('git --version', { encoding: 'utf8' }).trim();
32
+ const match = version.match(/(\d+\.\d+\.\d+)/);
33
+ return createCheck('Git', true, {
34
+ message: match ? `v${match[1]}` : 'installed',
35
+ });
36
+ } catch {
37
+ return createCheck('Git', false, {
38
+ severity: SEVERITY.CRITICAL,
39
+ remediation: 'Install Git from https://git-scm.com',
40
+ });
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Check package manager availability
46
+ */
47
+ function checkPackageManager() {
48
+ const managers = ['npm', 'yarn', 'pnpm', 'bun'];
49
+ let found = null;
50
+
51
+ for (const manager of managers) {
52
+ if (commandExists(manager)) {
53
+ found = manager;
54
+ break;
55
+ }
56
+ }
57
+
58
+ if (found) {
59
+ return createCheck('Package Manager', true, {
60
+ message: found,
61
+ });
62
+ }
63
+
64
+ return createCheck('Package Manager', false, {
65
+ severity: SEVERITY.CRITICAL,
66
+ remediation: 'Install Node.js (includes npm) from https://nodejs.org',
67
+ });
68
+ }
69
+
70
+ /**
71
+ * Check Git user.email is configured
72
+ */
73
+ function checkGitEmail() {
74
+ try {
75
+ const email = execSync('git config user.email', { encoding: 'utf8' }).trim();
76
+ return createCheck('Git user.email', !!email, {
77
+ message: email ? 'configured' : 'not set',
78
+ severity: email ? SEVERITY.INFO : SEVERITY.WARNING,
79
+ remediation: 'git config --global user.email "you@example.com"',
80
+ });
81
+ } catch {
82
+ return createCheck('Git user.email', false, {
83
+ severity: SEVERITY.WARNING,
84
+ remediation: 'git config --global user.email "you@example.com"',
85
+ });
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Check Git user.name is configured
91
+ */
92
+ function checkGitName() {
93
+ try {
94
+ const name = execSync('git config user.name', { encoding: 'utf8' }).trim();
95
+ return createCheck('Git user.name', !!name, {
96
+ message: name ? 'configured' : 'not set',
97
+ severity: name ? SEVERITY.INFO : SEVERITY.WARNING,
98
+ remediation: 'git config --global user.name "Your Name"',
99
+ });
100
+ } catch {
101
+ return createCheck('Git user.name', false, {
102
+ severity: SEVERITY.WARNING,
103
+ remediation: 'git config --global user.name "Your Name"',
104
+ });
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Run all environment checks
110
+ */
111
+ function verify() {
112
+ const checks = [
113
+ checkNodeVersion(),
114
+ checkGit(),
115
+ checkPackageManager(),
116
+ checkGitEmail(),
117
+ checkGitName(),
118
+ ];
119
+
120
+ return createResult(NAME, checks);
121
+ }
122
+
123
+ module.exports = { verify, NAME };