@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,188 @@
1
+ /**
2
+ * Hooks Verifier - Hook configuration and script validation
3
+ */
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const { execSync } = require('child_process');
8
+ const { createCheck, createResult, SEVERITY } = require('../lib/verify-formatter');
9
+ const { getClaudeDir } = require('../lib/utils');
10
+ const { getPluginRoot } = require('./plugin');
11
+
12
+ const NAME = 'Hooks';
13
+
14
+ /**
15
+ * Check hooks.json exists and is valid
16
+ */
17
+ function checkHooksJson() {
18
+ const pluginRoot = getPluginRoot();
19
+ const hooksPath = path.join(pluginRoot, 'hooks', 'hooks.json');
20
+
21
+ if (!fs.existsSync(hooksPath)) {
22
+ return createCheck('hooks.json exists', false, {
23
+ severity: SEVERITY.WARNING,
24
+ message: 'not found',
25
+ remediation: 'Create hooks/hooks.json with hook definitions',
26
+ });
27
+ }
28
+
29
+ try {
30
+ const content = fs.readFileSync(hooksPath, 'utf8');
31
+ const config = JSON.parse(content);
32
+
33
+ // Count total hooks across all events
34
+ let hookCount = 0;
35
+ if (config.hooks && typeof config.hooks === 'object') {
36
+ for (const event of Object.keys(config.hooks)) {
37
+ const eventHooks = config.hooks[event];
38
+ if (Array.isArray(eventHooks)) {
39
+ hookCount += eventHooks.length;
40
+ }
41
+ }
42
+ }
43
+
44
+ const eventCount = config.hooks ? Object.keys(config.hooks).length : 0;
45
+
46
+ return createCheck('hooks.json valid', true, {
47
+ message: `${eventCount} events, ${hookCount} hooks`,
48
+ });
49
+ } catch (err) {
50
+ return createCheck('hooks.json valid', false, {
51
+ severity: SEVERITY.CRITICAL,
52
+ message: 'JSON parse error',
53
+ remediation: 'Fix JSON syntax in hooks/hooks.json',
54
+ });
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Check global settings.json has hooks configured
60
+ */
61
+ function checkSettingsHooks() {
62
+ const settingsPath = path.join(getClaudeDir(), 'settings.json');
63
+
64
+ if (!fs.existsSync(settingsPath)) {
65
+ return createCheck('settings.json hooks', false, {
66
+ severity: SEVERITY.WARNING,
67
+ message: 'settings.json not found',
68
+ remediation: 'Create ~/.claude/settings.json with hooks configuration',
69
+ });
70
+ }
71
+
72
+ try {
73
+ const content = fs.readFileSync(settingsPath, 'utf8');
74
+ const settings = JSON.parse(content);
75
+
76
+ if (!settings.hooks || Object.keys(settings.hooks).length === 0) {
77
+ return createCheck('settings.json hooks', false, {
78
+ severity: SEVERITY.WARNING,
79
+ message: 'no hooks configured',
80
+ remediation: 'Add hooks section to ~/.claude/settings.json',
81
+ });
82
+ }
83
+
84
+ const eventCount = Object.keys(settings.hooks).length;
85
+ return createCheck('settings.json hooks', true, {
86
+ message: `${eventCount} events configured`,
87
+ });
88
+ } catch (err) {
89
+ return createCheck('settings.json hooks', false, {
90
+ severity: SEVERITY.WARNING,
91
+ message: 'cannot parse settings.json',
92
+ remediation: 'Fix JSON syntax in ~/.claude/settings.json',
93
+ });
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Check hook scripts exist
99
+ */
100
+ function checkHookScripts() {
101
+ const pluginRoot = getPluginRoot();
102
+ const scriptsDir = path.join(pluginRoot, 'scripts', 'hooks');
103
+ const checks = [];
104
+
105
+ // Key hook scripts to verify
106
+ const keyScripts = [
107
+ 'prompt-router.js',
108
+ 'session-start.js',
109
+ 'credential-check.js',
110
+ 'skill-injector.js',
111
+ 'quality-gate-enforcer.js',
112
+ ];
113
+
114
+ for (const script of keyScripts) {
115
+ const scriptPath = path.join(scriptsDir, script);
116
+ const exists = fs.existsSync(scriptPath);
117
+
118
+ checks.push(
119
+ createCheck(script, exists, {
120
+ severity: exists ? SEVERITY.INFO : SEVERITY.WARNING,
121
+ message: exists ? 'found' : 'missing',
122
+ remediation: exists ? null : `Create ${script} in scripts/hooks/`,
123
+ })
124
+ );
125
+ }
126
+
127
+ return checks;
128
+ }
129
+
130
+ /**
131
+ * Check hook scripts are syntactically valid
132
+ */
133
+ function checkHookScriptsSyntax() {
134
+ const pluginRoot = getPluginRoot();
135
+ const scriptsDir = path.join(pluginRoot, 'scripts', 'hooks');
136
+ const checks = [];
137
+
138
+ if (!fs.existsSync(scriptsDir)) {
139
+ return [
140
+ createCheck('hook scripts syntax', false, {
141
+ severity: SEVERITY.WARNING,
142
+ message: 'scripts/hooks/ not found',
143
+ }),
144
+ ];
145
+ }
146
+
147
+ const scripts = fs.readdirSync(scriptsDir).filter((f) => f.endsWith('.js'));
148
+
149
+ for (const script of scripts.slice(0, 5)) {
150
+ // Check first 5 scripts
151
+ const scriptPath = path.join(scriptsDir, script);
152
+ try {
153
+ // Use Node's syntax check
154
+ execSync(`node --check "${scriptPath}"`, { encoding: 'utf8', stdio: 'pipe' });
155
+ checks.push(
156
+ createCheck(`${script} syntax`, true, {
157
+ message: 'valid',
158
+ })
159
+ );
160
+ } catch (err) {
161
+ checks.push(
162
+ createCheck(`${script} syntax`, false, {
163
+ severity: SEVERITY.CRITICAL,
164
+ message: 'syntax error',
165
+ remediation: `Fix syntax error in scripts/hooks/${script}`,
166
+ })
167
+ );
168
+ }
169
+ }
170
+
171
+ return checks;
172
+ }
173
+
174
+ /**
175
+ * Run all hooks checks
176
+ */
177
+ function verify() {
178
+ const checks = [
179
+ checkHooksJson(),
180
+ checkSettingsHooks(),
181
+ ...checkHookScripts(),
182
+ ...checkHookScriptsSyntax(),
183
+ ];
184
+
185
+ return createResult(NAME, checks);
186
+ }
187
+
188
+ module.exports = { verify, NAME };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Verifiers Index - Registry and factories for verification modules
3
+ */
4
+
5
+ const { createCheck, createResult, SEVERITY } = require('../lib/verify-formatter');
6
+
7
+ // Export factories for use by verifier modules
8
+ module.exports = {
9
+ createCheck,
10
+ createResult,
11
+ SEVERITY,
12
+
13
+ // Verifier modules (lazy loaded to avoid circular deps)
14
+ get environment() {
15
+ return require('./environment');
16
+ },
17
+ get persistence() {
18
+ return require('./persistence');
19
+ },
20
+ get plugin() {
21
+ return require('./plugin');
22
+ },
23
+ get config() {
24
+ return require('./config');
25
+ },
26
+ get hooks() {
27
+ return require('./hooks');
28
+ },
29
+ get skills() {
30
+ return require('./skills');
31
+ },
32
+ get agents() {
33
+ return require('./agents');
34
+ },
35
+
36
+ // Execution order (dependency-based)
37
+ executionOrder: ['environment', 'persistence', 'plugin', 'config', 'hooks', 'skills', 'agents'],
38
+ };
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Persistence Verifier - ~/.claude directory checks
3
+ */
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const { createCheck, createResult, SEVERITY } = require('../lib/verify-formatter');
8
+ const { getClaudeDir, ensureDir } = require('../lib/utils');
9
+
10
+ const NAME = 'Persistence';
11
+
12
+ /**
13
+ * Check ~/.claude exists
14
+ */
15
+ function checkClaudeDir() {
16
+ const claudeDir = getClaudeDir();
17
+ const exists = fs.existsSync(claudeDir);
18
+
19
+ return createCheck('~/.claude exists', exists, {
20
+ severity: exists ? SEVERITY.INFO : SEVERITY.CRITICAL,
21
+ remediation: `Create directory: mkdir "${claudeDir}"`,
22
+ });
23
+ }
24
+
25
+ /**
26
+ * Check ~/.claude is writable
27
+ */
28
+ function checkClaudeDirWritable() {
29
+ const claudeDir = getClaudeDir();
30
+
31
+ if (!fs.existsSync(claudeDir)) {
32
+ return createCheck('~/.claude writable', false, {
33
+ severity: SEVERITY.CRITICAL,
34
+ message: 'directory missing',
35
+ remediation: `Create directory: mkdir "${claudeDir}"`,
36
+ });
37
+ }
38
+
39
+ try {
40
+ const testFile = path.join(claudeDir, '.verify-test');
41
+ fs.writeFileSync(testFile, 'test');
42
+ fs.unlinkSync(testFile);
43
+ return createCheck('~/.claude writable', true);
44
+ } catch (err) {
45
+ return createCheck('~/.claude writable', false, {
46
+ severity: SEVERITY.CRITICAL,
47
+ message: err.code,
48
+ remediation: 'Fix permissions on ~/.claude directory',
49
+ });
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Check sessions directory
55
+ */
56
+ function checkSessionsDir() {
57
+ const sessionsDir = path.join(getClaudeDir(), 'sessions');
58
+
59
+ if (fs.existsSync(sessionsDir)) {
60
+ return createCheck('sessions/ exists', true);
61
+ }
62
+
63
+ // Try to create it
64
+ try {
65
+ ensureDir(sessionsDir);
66
+ return createCheck('sessions/ exists', true, {
67
+ message: 'created',
68
+ });
69
+ } catch {
70
+ return createCheck('sessions/ exists', false, {
71
+ severity: SEVERITY.WARNING,
72
+ remediation: `Create directory: mkdir "${sessionsDir}"`,
73
+ });
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Check memory directory
79
+ */
80
+ function checkMemoryDir() {
81
+ const memoryDir = path.join(getClaudeDir(), 'memory');
82
+
83
+ if (fs.existsSync(memoryDir)) {
84
+ return createCheck('memory/ exists', true);
85
+ }
86
+
87
+ // Try to create it
88
+ try {
89
+ ensureDir(memoryDir);
90
+ return createCheck('memory/ exists', true, {
91
+ message: 'created',
92
+ });
93
+ } catch {
94
+ return createCheck('memory/ exists', false, {
95
+ severity: SEVERITY.WARNING,
96
+ remediation: `Create directory: mkdir "${memoryDir}"`,
97
+ });
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Check plans directory
103
+ */
104
+ function checkPlansDir() {
105
+ const plansDir = path.join(getClaudeDir(), 'plans');
106
+
107
+ if (fs.existsSync(plansDir)) {
108
+ return createCheck('plans/ exists', true);
109
+ }
110
+
111
+ // Try to create it
112
+ try {
113
+ ensureDir(plansDir);
114
+ return createCheck('plans/ exists', true, {
115
+ message: 'created',
116
+ });
117
+ } catch {
118
+ return createCheck('plans/ exists', false, {
119
+ severity: SEVERITY.WARNING,
120
+ remediation: `Create directory: mkdir "${plansDir}"`,
121
+ });
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Run all persistence checks
127
+ */
128
+ function verify() {
129
+ const checks = [
130
+ checkClaudeDir(),
131
+ checkClaudeDirWritable(),
132
+ checkSessionsDir(),
133
+ checkMemoryDir(),
134
+ checkPlansDir(),
135
+ ];
136
+
137
+ return createResult(NAME, checks);
138
+ }
139
+
140
+ module.exports = { verify, NAME };
@@ -0,0 +1,215 @@
1
+ /**
2
+ * Plugin Verifier - plugin.json and directory structure validation
3
+ */
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const { createCheck, createResult, SEVERITY } = require('../lib/verify-formatter');
8
+
9
+ const NAME = 'Plugin';
10
+
11
+ /**
12
+ * Get plugin root directory (where assets like commands/, skills/, hooks/ live)
13
+ * Note: plugin.json is in .claude-plugin/ but paths are relative to parent (repo root)
14
+ */
15
+ function getPluginRoot() {
16
+ // Check multiple possible locations for plugin.json
17
+ const possiblePluginJsonLocations = [
18
+ path.join(process.cwd(), '.claude-plugin', 'plugin.json'),
19
+ path.join(process.cwd(), 'plugin.json'),
20
+ path.join(__dirname, '..', '..', '.claude-plugin', 'plugin.json'),
21
+ path.join(__dirname, '..', '..', 'plugin.json'),
22
+ ];
23
+
24
+ for (const pluginPath of possiblePluginJsonLocations) {
25
+ if (fs.existsSync(pluginPath)) {
26
+ // Return the repo root (parent of .claude-plugin)
27
+ // because that's where commands/, skills/, hooks/ actually live
28
+ const pluginDir = path.dirname(pluginPath);
29
+ if (pluginDir.endsWith('.claude-plugin')) {
30
+ return path.dirname(pluginDir); // Return parent of .claude-plugin
31
+ }
32
+ return pluginDir;
33
+ }
34
+ }
35
+
36
+ return path.join(__dirname, '..', '..');
37
+ }
38
+
39
+ /**
40
+ * Get path to plugin.json file
41
+ */
42
+ function getPluginJsonPath() {
43
+ const root = getPluginRoot();
44
+ const locations = [
45
+ path.join(root, '.claude-plugin', 'plugin.json'),
46
+ path.join(root, 'plugin.json'),
47
+ ];
48
+
49
+ for (const loc of locations) {
50
+ if (fs.existsSync(loc)) {
51
+ return loc;
52
+ }
53
+ }
54
+
55
+ return path.join(root, '.claude-plugin', 'plugin.json');
56
+ }
57
+
58
+ /**
59
+ * Check plugin.json exists and is valid
60
+ */
61
+ function checkPluginJson() {
62
+ const pluginPath = getPluginJsonPath();
63
+
64
+ if (!fs.existsSync(pluginPath)) {
65
+ return createCheck('plugin.json exists', false, {
66
+ severity: SEVERITY.CRITICAL,
67
+ remediation: 'Re-clone the repository or check plugin.json location',
68
+ });
69
+ }
70
+
71
+ try {
72
+ const content = fs.readFileSync(pluginPath, 'utf8');
73
+ const plugin = JSON.parse(content);
74
+
75
+ if (!plugin.name) {
76
+ return createCheck('plugin.json valid', false, {
77
+ severity: SEVERITY.CRITICAL,
78
+ message: 'missing name field',
79
+ remediation: 'Add "name" field to plugin.json',
80
+ });
81
+ }
82
+
83
+ return createCheck('plugin.json valid', true, {
84
+ message: plugin.name,
85
+ });
86
+ } catch (err) {
87
+ return createCheck('plugin.json valid', false, {
88
+ severity: SEVERITY.CRITICAL,
89
+ message: 'JSON parse error',
90
+ remediation: 'Fix JSON syntax in plugin.json',
91
+ });
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Check plugin has required paths configured
97
+ */
98
+ function checkPluginPaths() {
99
+ const pluginRoot = getPluginRoot();
100
+ const pluginPath = getPluginJsonPath();
101
+
102
+ try {
103
+ const plugin = JSON.parse(fs.readFileSync(pluginPath, 'utf8'));
104
+ const checks = [];
105
+
106
+ // Check commands path
107
+ if (plugin.commands) {
108
+ const commandsDir = path.join(pluginRoot, plugin.commands);
109
+ const exists = fs.existsSync(commandsDir);
110
+ const count = exists
111
+ ? fs.readdirSync(commandsDir).filter((f) => f.endsWith('.md')).length
112
+ : 0;
113
+ checks.push(
114
+ createCheck('commands/', exists, {
115
+ message: exists ? `${count} files` : 'missing',
116
+ severity: exists ? SEVERITY.INFO : SEVERITY.CRITICAL,
117
+ remediation: 'Re-clone repository or check commands path in plugin.json',
118
+ })
119
+ );
120
+ } else {
121
+ checks.push(
122
+ createCheck('commands/ configured', false, {
123
+ severity: SEVERITY.CRITICAL,
124
+ remediation: 'Add "commands" path to plugin.json',
125
+ })
126
+ );
127
+ }
128
+
129
+ // Check skills path
130
+ if (plugin.skills) {
131
+ const skillsDir = path.join(pluginRoot, plugin.skills);
132
+ const exists = fs.existsSync(skillsDir);
133
+ const count = exists
134
+ ? fs
135
+ .readdirSync(skillsDir)
136
+ .filter((f) => fs.statSync(path.join(skillsDir, f)).isDirectory()).length
137
+ : 0;
138
+ checks.push(
139
+ createCheck('skills/', exists, {
140
+ message: exists ? `${count} dirs` : 'missing',
141
+ severity: exists ? SEVERITY.INFO : SEVERITY.CRITICAL,
142
+ remediation: 'Re-clone repository or check skills path in plugin.json',
143
+ })
144
+ );
145
+ } else {
146
+ checks.push(
147
+ createCheck('skills/ configured', false, {
148
+ severity: SEVERITY.CRITICAL,
149
+ remediation: 'Add "skills" path to plugin.json',
150
+ })
151
+ );
152
+ }
153
+
154
+ // Check hooks path
155
+ if (plugin.hooks) {
156
+ const hooksDir = path.join(pluginRoot, plugin.hooks);
157
+ const exists = fs.existsSync(hooksDir);
158
+ checks.push(
159
+ createCheck('hooks/', exists, {
160
+ message: exists ? 'found' : 'missing',
161
+ severity: exists ? SEVERITY.INFO : SEVERITY.CRITICAL,
162
+ remediation: 'Re-clone repository or check hooks path in plugin.json',
163
+ })
164
+ );
165
+ } else {
166
+ checks.push(
167
+ createCheck('hooks/ configured', false, {
168
+ severity: SEVERITY.WARNING,
169
+ remediation: 'Add "hooks" path to plugin.json',
170
+ })
171
+ );
172
+ }
173
+
174
+ return checks;
175
+ } catch {
176
+ return [
177
+ createCheck('plugin paths', false, {
178
+ severity: SEVERITY.CRITICAL,
179
+ message: 'cannot read plugin.json',
180
+ }),
181
+ ];
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Check agents directory (optional but recommended)
187
+ */
188
+ function checkAgentsDir() {
189
+ const pluginRoot = getPluginRoot();
190
+ const agentsDir = path.join(pluginRoot, 'agents');
191
+
192
+ if (fs.existsSync(agentsDir)) {
193
+ const count = fs.readdirSync(agentsDir).filter((f) => f.endsWith('.md')).length;
194
+ return createCheck('agents/', true, {
195
+ message: `${count} files`,
196
+ });
197
+ }
198
+
199
+ return createCheck('agents/', false, {
200
+ severity: SEVERITY.WARNING,
201
+ message: 'not found',
202
+ remediation: 'Create agents/ directory for agent definitions',
203
+ });
204
+ }
205
+
206
+ /**
207
+ * Run all plugin checks
208
+ */
209
+ function verify() {
210
+ const checks = [checkPluginJson(), ...checkPluginPaths(), checkAgentsDir()];
211
+
212
+ return createResult(NAME, checks);
213
+ }
214
+
215
+ module.exports = { verify, NAME, getPluginRoot, getPluginJsonPath };