agentsys 5.0.2 → 5.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 (264) hide show
  1. package/.claude-plugin/marketplace.json +21 -14
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/AGENTS.md +2 -1
  4. package/CHANGELOG.md +24 -1
  5. package/README.md +7 -6
  6. package/adapters/codex/skills/agnix/SKILL.md +0 -1
  7. package/adapters/codex/skills/audit-project/SKILL.md +0 -1
  8. package/adapters/codex/skills/audit-project-agents/SKILL.md +0 -1
  9. package/adapters/codex/skills/audit-project-github/SKILL.md +0 -1
  10. package/adapters/codex/skills/consult/SKILL.md +133 -59
  11. package/adapters/codex/skills/debate/SKILL.md +214 -0
  12. package/adapters/codex/skills/delivery-approval/SKILL.md +0 -1
  13. package/adapters/codex/skills/deslop/SKILL.md +0 -1
  14. package/adapters/codex/skills/drift-detect/SKILL.md +0 -1
  15. package/adapters/codex/skills/enhance/SKILL.md +0 -1
  16. package/adapters/codex/skills/learn/SKILL.md +0 -1
  17. package/adapters/codex/skills/next-task/SKILL.md +0 -1
  18. package/adapters/codex/skills/perf/SKILL.md +0 -1
  19. package/adapters/codex/skills/repo-map/SKILL.md +0 -1
  20. package/adapters/codex/skills/ship/SKILL.md +0 -1
  21. package/adapters/codex/skills/ship-ci-review-loop/SKILL.md +0 -1
  22. package/adapters/codex/skills/ship-deployment/SKILL.md +0 -1
  23. package/adapters/codex/skills/ship-error-handling/SKILL.md +0 -1
  24. package/adapters/codex/skills/sync-docs/SKILL.md +0 -1
  25. package/adapters/opencode/agents/agent-enhancer.md +0 -1
  26. package/adapters/opencode/agents/agnix-agent.md +0 -1
  27. package/adapters/opencode/agents/ci-fixer.md +0 -1
  28. package/adapters/opencode/agents/ci-monitor.md +0 -1
  29. package/adapters/opencode/agents/claudemd-enhancer.md +0 -1
  30. package/adapters/opencode/agents/consult-agent.md +123 -31
  31. package/adapters/opencode/agents/cross-file-enhancer.md +0 -1
  32. package/adapters/opencode/agents/debate-orchestrator.md +169 -0
  33. package/adapters/opencode/agents/delivery-validator.md +0 -1
  34. package/adapters/opencode/agents/deslop-agent.md +0 -1
  35. package/adapters/opencode/agents/docs-enhancer.md +0 -1
  36. package/adapters/opencode/agents/exploration-agent.md +0 -1
  37. package/adapters/opencode/agents/hooks-enhancer.md +0 -1
  38. package/adapters/opencode/agents/implementation-agent.md +0 -1
  39. package/adapters/opencode/agents/learn-agent.md +0 -1
  40. package/adapters/opencode/agents/map-validator.md +0 -1
  41. package/adapters/opencode/agents/perf-analyzer.md +0 -1
  42. package/adapters/opencode/agents/perf-code-paths.md +0 -1
  43. package/adapters/opencode/agents/perf-investigation-logger.md +0 -1
  44. package/adapters/opencode/agents/perf-orchestrator.md +0 -1
  45. package/adapters/opencode/agents/perf-theory-gatherer.md +0 -1
  46. package/adapters/opencode/agents/perf-theory-tester.md +0 -1
  47. package/adapters/opencode/agents/plan-synthesizer.md +0 -1
  48. package/adapters/opencode/agents/planning-agent.md +0 -1
  49. package/adapters/opencode/agents/plugin-enhancer.md +0 -1
  50. package/adapters/opencode/agents/prompt-enhancer.md +0 -1
  51. package/adapters/opencode/agents/simple-fixer.md +0 -1
  52. package/adapters/opencode/agents/skills-enhancer.md +0 -1
  53. package/adapters/opencode/agents/sync-docs-agent.md +0 -1
  54. package/adapters/opencode/agents/task-discoverer.md +0 -1
  55. package/adapters/opencode/agents/test-coverage-checker.md +0 -1
  56. package/adapters/opencode/agents/worktree-manager.md +0 -1
  57. package/adapters/opencode/commands/agnix.md +0 -1
  58. package/adapters/opencode/commands/audit-project-agents.md +0 -1
  59. package/adapters/opencode/commands/audit-project-github.md +0 -1
  60. package/adapters/opencode/commands/audit-project.md +0 -1
  61. package/adapters/opencode/commands/consult.md +134 -59
  62. package/adapters/opencode/commands/debate.md +224 -0
  63. package/adapters/opencode/commands/delivery-approval.md +0 -1
  64. package/adapters/opencode/commands/deslop.md +0 -1
  65. package/adapters/opencode/commands/drift-detect.md +0 -1
  66. package/adapters/opencode/commands/enhance.md +0 -1
  67. package/adapters/opencode/commands/learn.md +0 -1
  68. package/adapters/opencode/commands/next-task.md +0 -1
  69. package/adapters/opencode/commands/perf.md +0 -1
  70. package/adapters/opencode/commands/repo-map.md +0 -1
  71. package/adapters/opencode/commands/ship-ci-review-loop.md +0 -1
  72. package/adapters/opencode/commands/ship-deployment.md +0 -1
  73. package/adapters/opencode/commands/ship-error-handling.md +0 -1
  74. package/adapters/opencode/commands/ship.md +0 -1
  75. package/adapters/opencode/commands/sync-docs.md +0 -1
  76. package/adapters/opencode/skills/agnix/SKILL.md +1 -2
  77. package/adapters/opencode/skills/consult/SKILL.md +41 -27
  78. package/adapters/opencode/skills/debate/SKILL.md +245 -0
  79. package/adapters/opencode/skills/deslop/SKILL.md +1 -2
  80. package/adapters/opencode/skills/discover-tasks/SKILL.md +1 -2
  81. package/adapters/opencode/skills/drift-analysis/SKILL.md +1 -2
  82. package/adapters/opencode/skills/enhance-agent-prompts/SKILL.md +1 -2
  83. package/adapters/opencode/skills/enhance-claude-memory/SKILL.md +1 -2
  84. package/adapters/opencode/skills/enhance-cross-file/SKILL.md +1 -2
  85. package/adapters/opencode/skills/enhance-docs/SKILL.md +1 -2
  86. package/adapters/opencode/skills/enhance-hooks/SKILL.md +1 -2
  87. package/adapters/opencode/skills/enhance-orchestrator/SKILL.md +1 -2
  88. package/adapters/opencode/skills/enhance-plugins/SKILL.md +1 -2
  89. package/adapters/opencode/skills/enhance-prompts/SKILL.md +1 -2
  90. package/adapters/opencode/skills/enhance-skills/SKILL.md +1 -2
  91. package/adapters/opencode/skills/learn/SKILL.md +1 -2
  92. package/adapters/opencode/skills/orchestrate-review/SKILL.md +0 -1
  93. package/adapters/opencode/skills/perf-analyzer/SKILL.md +1 -2
  94. package/adapters/opencode/skills/perf-baseline-manager/SKILL.md +1 -2
  95. package/adapters/opencode/skills/perf-benchmarker/SKILL.md +1 -2
  96. package/adapters/opencode/skills/perf-code-paths/SKILL.md +1 -2
  97. package/adapters/opencode/skills/perf-investigation-logger/SKILL.md +1 -2
  98. package/adapters/opencode/skills/perf-profiler/SKILL.md +1 -2
  99. package/adapters/opencode/skills/perf-theory-gatherer/SKILL.md +1 -2
  100. package/adapters/opencode/skills/perf-theory-tester/SKILL.md +1 -2
  101. package/adapters/opencode/skills/repo-mapping/SKILL.md +1 -2
  102. package/adapters/opencode/skills/sync-docs/SKILL.md +1 -2
  103. package/adapters/opencode/skills/validate-delivery/SKILL.md +1 -2
  104. package/lib/adapter-transforms.js +24 -4
  105. package/package.json +1 -1
  106. package/plugins/agnix/.claude-plugin/plugin.json +1 -1
  107. package/plugins/agnix/skills/agnix/SKILL.md +1 -1
  108. package/plugins/audit-project/.claude-plugin/plugin.json +1 -1
  109. package/plugins/audit-project/lib/adapter-transforms.js +24 -4
  110. package/plugins/consult/.claude-plugin/plugin.json +1 -1
  111. package/plugins/consult/agents/consult-agent.md +123 -30
  112. package/plugins/consult/commands/consult.md +136 -60
  113. package/plugins/consult/skills/consult/SKILL.md +39 -24
  114. package/plugins/debate/.claude-plugin/plugin.json +21 -0
  115. package/plugins/debate/agents/debate-orchestrator.md +175 -0
  116. package/plugins/debate/commands/debate.md +221 -0
  117. package/plugins/debate/lib/adapter-transforms.js +298 -0
  118. package/plugins/debate/lib/collectors/codebase.js +392 -0
  119. package/plugins/debate/lib/collectors/docs-patterns.js +713 -0
  120. package/plugins/debate/lib/collectors/documentation.js +219 -0
  121. package/plugins/debate/lib/collectors/github.js +330 -0
  122. package/plugins/debate/lib/collectors/index.js +126 -0
  123. package/plugins/debate/lib/config/index.js +14 -0
  124. package/plugins/debate/lib/cross-platform/index.js +539 -0
  125. package/plugins/debate/lib/discovery/index.js +352 -0
  126. package/plugins/debate/lib/drift-detect/collectors.js +37 -0
  127. package/plugins/debate/lib/enhance/agent-analyzer.js +421 -0
  128. package/plugins/debate/lib/enhance/agent-patterns.js +571 -0
  129. package/plugins/debate/lib/enhance/auto-suppression.js +622 -0
  130. package/plugins/debate/lib/enhance/benchmark.js +417 -0
  131. package/plugins/debate/lib/enhance/cross-file-analyzer.js +930 -0
  132. package/plugins/debate/lib/enhance/cross-file-patterns.js +370 -0
  133. package/plugins/debate/lib/enhance/docs-analyzer.js +325 -0
  134. package/plugins/debate/lib/enhance/docs-patterns.js +671 -0
  135. package/plugins/debate/lib/enhance/fixer.js +721 -0
  136. package/plugins/debate/lib/enhance/hook-analyzer.js +135 -0
  137. package/plugins/debate/lib/enhance/hook-patterns.js +40 -0
  138. package/plugins/debate/lib/enhance/index.js +127 -0
  139. package/plugins/debate/lib/enhance/plugin-analyzer.js +402 -0
  140. package/plugins/debate/lib/enhance/plugin-patterns.js +326 -0
  141. package/plugins/debate/lib/enhance/projectmemory-analyzer.js +551 -0
  142. package/plugins/debate/lib/enhance/projectmemory-patterns.js +617 -0
  143. package/plugins/debate/lib/enhance/prompt-analyzer.js +457 -0
  144. package/plugins/debate/lib/enhance/prompt-patterns.js +1484 -0
  145. package/plugins/debate/lib/enhance/reporter.js +1348 -0
  146. package/plugins/debate/lib/enhance/security-patterns.js +284 -0
  147. package/plugins/debate/lib/enhance/skill-analyzer.js +182 -0
  148. package/plugins/debate/lib/enhance/skill-patterns.js +147 -0
  149. package/plugins/debate/lib/enhance/suppression.js +352 -0
  150. package/plugins/debate/lib/enhance/tool-patterns.js +373 -0
  151. package/plugins/debate/lib/index.js +270 -0
  152. package/plugins/debate/lib/patterns/cli-enhancers.js +611 -0
  153. package/plugins/debate/lib/patterns/pipeline.js +948 -0
  154. package/plugins/debate/lib/patterns/review-patterns.js +558 -0
  155. package/plugins/debate/lib/patterns/slop-analyzers.js +2305 -0
  156. package/plugins/debate/lib/patterns/slop-patterns.js +1187 -0
  157. package/plugins/debate/lib/perf/analyzer/index.js +22 -0
  158. package/plugins/debate/lib/perf/argument-parser.js +105 -0
  159. package/plugins/debate/lib/perf/baseline-comparator.js +50 -0
  160. package/plugins/debate/lib/perf/baseline-store.js +127 -0
  161. package/plugins/debate/lib/perf/benchmark-runner.js +404 -0
  162. package/plugins/debate/lib/perf/breaking-point-finder.js +52 -0
  163. package/plugins/debate/lib/perf/breaking-point-runner.js +60 -0
  164. package/plugins/debate/lib/perf/checkpoint.js +123 -0
  165. package/plugins/debate/lib/perf/code-paths.js +86 -0
  166. package/plugins/debate/lib/perf/consolidation.js +37 -0
  167. package/plugins/debate/lib/perf/constraint-runner.js +71 -0
  168. package/plugins/debate/lib/perf/experiment-runner.js +32 -0
  169. package/plugins/debate/lib/perf/index.js +41 -0
  170. package/plugins/debate/lib/perf/investigation-state.js +874 -0
  171. package/plugins/debate/lib/perf/optimization-runner.js +79 -0
  172. package/plugins/debate/lib/perf/profilers/go.js +22 -0
  173. package/plugins/debate/lib/perf/profilers/index.js +46 -0
  174. package/plugins/debate/lib/perf/profilers/java.js +23 -0
  175. package/plugins/debate/lib/perf/profilers/node.js +27 -0
  176. package/plugins/debate/lib/perf/profilers/python.js +23 -0
  177. package/plugins/debate/lib/perf/profilers/rust.js +23 -0
  178. package/plugins/debate/lib/perf/profiling-runner.js +75 -0
  179. package/plugins/debate/lib/perf/schemas.js +140 -0
  180. package/plugins/debate/lib/platform/detect-platform.js +413 -0
  181. package/plugins/debate/lib/platform/detection-configs.js +93 -0
  182. package/plugins/debate/lib/platform/state-dir.js +132 -0
  183. package/plugins/debate/lib/platform/verify-tools.js +182 -0
  184. package/plugins/debate/lib/repo-map/cache.js +152 -0
  185. package/plugins/debate/lib/repo-map/concurrency.js +29 -0
  186. package/plugins/debate/lib/repo-map/index.js +222 -0
  187. package/plugins/debate/lib/repo-map/installer.js +212 -0
  188. package/plugins/debate/lib/repo-map/queries/go.js +27 -0
  189. package/plugins/debate/lib/repo-map/queries/index.js +100 -0
  190. package/plugins/debate/lib/repo-map/queries/java.js +38 -0
  191. package/plugins/debate/lib/repo-map/queries/javascript.js +55 -0
  192. package/plugins/debate/lib/repo-map/queries/python.js +24 -0
  193. package/plugins/debate/lib/repo-map/queries/rust.js +73 -0
  194. package/plugins/debate/lib/repo-map/queries/typescript.js +38 -0
  195. package/plugins/debate/lib/repo-map/runner.js +1364 -0
  196. package/plugins/debate/lib/repo-map/updater.js +562 -0
  197. package/plugins/debate/lib/repo-map/usage-analyzer.js +407 -0
  198. package/plugins/debate/lib/schemas/plugin-manifest.schema.json +57 -0
  199. package/plugins/debate/lib/schemas/validator.js +247 -0
  200. package/plugins/debate/lib/sources/custom-handler.js +199 -0
  201. package/plugins/debate/lib/sources/policy-questions.js +246 -0
  202. package/plugins/debate/lib/sources/source-cache.js +165 -0
  203. package/plugins/debate/lib/state/workflow-state.js +576 -0
  204. package/plugins/debate/lib/types/agent-frontmatter.d.ts +134 -0
  205. package/plugins/debate/lib/types/command-frontmatter.d.ts +107 -0
  206. package/plugins/debate/lib/types/hook-frontmatter.d.ts +115 -0
  207. package/plugins/debate/lib/types/index.d.ts +84 -0
  208. package/plugins/debate/lib/types/plugin-manifest.d.ts +102 -0
  209. package/plugins/debate/lib/types/skill-frontmatter.d.ts +89 -0
  210. package/plugins/debate/lib/utils/atomic-write.js +94 -0
  211. package/plugins/debate/lib/utils/cache-manager.js +159 -0
  212. package/plugins/debate/lib/utils/command-parser.js +0 -0
  213. package/plugins/debate/lib/utils/context-optimizer.js +300 -0
  214. package/plugins/debate/lib/utils/deprecation.js +37 -0
  215. package/plugins/debate/lib/utils/shell-escape.js +88 -0
  216. package/plugins/debate/lib/utils/state-helpers.js +61 -0
  217. package/plugins/debate/skills/debate/SKILL.md +264 -0
  218. package/plugins/deslop/.claude-plugin/plugin.json +1 -1
  219. package/plugins/deslop/lib/adapter-transforms.js +24 -4
  220. package/plugins/deslop/skills/deslop/SKILL.md +1 -1
  221. package/plugins/drift-detect/.claude-plugin/plugin.json +1 -1
  222. package/plugins/drift-detect/lib/adapter-transforms.js +24 -4
  223. package/plugins/drift-detect/skills/drift-analysis/SKILL.md +1 -1
  224. package/plugins/enhance/.claude-plugin/plugin.json +1 -1
  225. package/plugins/enhance/lib/adapter-transforms.js +24 -4
  226. package/plugins/enhance/skills/enhance-agent-prompts/SKILL.md +1 -1
  227. package/plugins/enhance/skills/enhance-claude-memory/SKILL.md +1 -1
  228. package/plugins/enhance/skills/enhance-cross-file/SKILL.md +1 -1
  229. package/plugins/enhance/skills/enhance-docs/SKILL.md +1 -1
  230. package/plugins/enhance/skills/enhance-hooks/SKILL.md +1 -1
  231. package/plugins/enhance/skills/enhance-orchestrator/SKILL.md +1 -1
  232. package/plugins/enhance/skills/enhance-plugins/SKILL.md +1 -1
  233. package/plugins/enhance/skills/enhance-prompts/SKILL.md +1 -1
  234. package/plugins/enhance/skills/enhance-skills/SKILL.md +1 -1
  235. package/plugins/learn/.claude-plugin/plugin.json +1 -1
  236. package/plugins/learn/agents/learn-agent.md +1 -1
  237. package/plugins/learn/lib/adapter-transforms.js +24 -4
  238. package/plugins/learn/skills/learn/SKILL.md +1 -1
  239. package/plugins/next-task/.claude-plugin/plugin.json +1 -1
  240. package/plugins/next-task/agents/exploration-agent.md +1 -1
  241. package/plugins/next-task/lib/adapter-transforms.js +24 -4
  242. package/plugins/next-task/skills/discover-tasks/SKILL.md +1 -1
  243. package/plugins/next-task/skills/validate-delivery/SKILL.md +1 -1
  244. package/plugins/perf/.claude-plugin/plugin.json +1 -1
  245. package/plugins/perf/lib/adapter-transforms.js +24 -4
  246. package/plugins/perf/skills/perf-analyzer/SKILL.md +1 -1
  247. package/plugins/perf/skills/perf-baseline-manager/SKILL.md +1 -1
  248. package/plugins/perf/skills/perf-benchmarker/SKILL.md +1 -1
  249. package/plugins/perf/skills/perf-code-paths/SKILL.md +1 -1
  250. package/plugins/perf/skills/perf-investigation-logger/SKILL.md +1 -1
  251. package/plugins/perf/skills/perf-profiler/SKILL.md +1 -1
  252. package/plugins/perf/skills/perf-theory-gatherer/SKILL.md +1 -1
  253. package/plugins/perf/skills/perf-theory-tester/SKILL.md +1 -1
  254. package/plugins/repo-map/.claude-plugin/plugin.json +1 -1
  255. package/plugins/repo-map/lib/adapter-transforms.js +24 -4
  256. package/plugins/ship/.claude-plugin/plugin.json +1 -1
  257. package/plugins/ship/lib/adapter-transforms.js +24 -4
  258. package/plugins/sync-docs/.claude-plugin/plugin.json +1 -1
  259. package/plugins/sync-docs/lib/adapter-transforms.js +24 -4
  260. package/plugins/sync-docs/skills/sync-docs/SKILL.md +1 -1
  261. package/scripts/gen-adapters.js +6 -7
  262. package/scripts/generate-docs.js +4 -2
  263. package/scripts/plugins.txt +1 -0
  264. package/site/content.json +6 -6
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Hook analyzer for /enhance.
3
+ */
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const { hookPatterns } = require('./hook-patterns');
8
+ const { parseMarkdownFrontmatter } = require('./agent-analyzer');
9
+
10
+ function analyzeHook(hookPath) {
11
+ const results = {
12
+ hookName: path.basename(hookPath, '.md'),
13
+ hookPath,
14
+ structureIssues: []
15
+ };
16
+
17
+ if (!fs.existsSync(hookPath)) {
18
+ results.structureIssues.push({
19
+ issue: 'File not found',
20
+ file: hookPath,
21
+ certainty: 'HIGH',
22
+ patternId: 'file_not_found'
23
+ });
24
+ return results;
25
+ }
26
+
27
+ let content = '';
28
+ try {
29
+ content = fs.readFileSync(hookPath, 'utf8');
30
+ } catch (err) {
31
+ results.structureIssues.push({
32
+ issue: `Failed to read file: ${err.message}`,
33
+ file: hookPath,
34
+ certainty: 'HIGH',
35
+ patternId: 'read_error'
36
+ });
37
+ return results;
38
+ }
39
+
40
+ const missingFm = hookPatterns.missing_frontmatter.check(content);
41
+ if (missingFm) {
42
+ results.structureIssues.push({
43
+ ...missingFm,
44
+ file: hookPath,
45
+ certainty: hookPatterns.missing_frontmatter.certainty,
46
+ patternId: hookPatterns.missing_frontmatter.id
47
+ });
48
+ }
49
+
50
+ const { frontmatter } = parseMarkdownFrontmatter(content);
51
+ const missingName = hookPatterns.missing_name.check(frontmatter);
52
+ if (missingName) {
53
+ results.structureIssues.push({
54
+ ...missingName,
55
+ file: hookPath,
56
+ certainty: hookPatterns.missing_name.certainty,
57
+ patternId: hookPatterns.missing_name.id
58
+ });
59
+ }
60
+
61
+ const missingDescription = hookPatterns.missing_description.check(frontmatter);
62
+ if (missingDescription) {
63
+ results.structureIssues.push({
64
+ ...missingDescription,
65
+ file: hookPath,
66
+ certainty: hookPatterns.missing_description.certainty,
67
+ patternId: hookPatterns.missing_description.id
68
+ });
69
+ }
70
+
71
+ return results;
72
+ }
73
+
74
+ function analyzeAllHooks(hooksDir) {
75
+ const results = [];
76
+ if (!fs.existsSync(hooksDir)) return results;
77
+
78
+ const hookFiles = [];
79
+ const skipDirs = new Set(['node_modules', '.git', 'dist', 'build', 'out', 'target']);
80
+
81
+ function walk(dir) {
82
+ let entries;
83
+ try {
84
+ entries = fs.readdirSync(dir, { withFileTypes: true });
85
+ } catch (err) {
86
+ return;
87
+ }
88
+
89
+ for (const entry of entries) {
90
+ const fullPath = path.join(dir, entry.name);
91
+ if (entry.isDirectory()) {
92
+ if (!skipDirs.has(entry.name)) {
93
+ walk(fullPath);
94
+ }
95
+ continue;
96
+ }
97
+
98
+ if (!entry.isFile() || !entry.name.endsWith('.md')) continue;
99
+ const parts = fullPath.split(path.sep);
100
+ if (parts.includes('hooks')) {
101
+ hookFiles.push(fullPath);
102
+ }
103
+ }
104
+ }
105
+
106
+ walk(hooksDir);
107
+
108
+ for (const file of hookFiles) {
109
+ results.push(analyzeHook(file));
110
+ }
111
+
112
+ return results;
113
+ }
114
+
115
+ function analyze(options = {}) {
116
+ const {
117
+ hook,
118
+ hooksDir = 'plugins/enhance/hooks'
119
+ } = options;
120
+
121
+ if (hook) {
122
+ const hookPath = hook.endsWith('.md')
123
+ ? hook
124
+ : path.join(hooksDir, `${hook}.md`);
125
+ return analyzeHook(hookPath);
126
+ }
127
+
128
+ return analyzeAllHooks(hooksDir);
129
+ }
130
+
131
+ module.exports = {
132
+ analyzeHook,
133
+ analyzeAllHooks,
134
+ analyze
135
+ };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Hook patterns for /enhance.
3
+ */
4
+
5
+ const hookPatterns = {
6
+ missing_frontmatter: {
7
+ id: 'missing_frontmatter',
8
+ certainty: 'HIGH',
9
+ check(content) {
10
+ if (!content || !content.trim().startsWith('---')) {
11
+ return { issue: 'Missing YAML frontmatter in hook file' };
12
+ }
13
+ return null;
14
+ }
15
+ },
16
+ missing_name: {
17
+ id: 'missing_name',
18
+ certainty: 'HIGH',
19
+ check(frontmatter) {
20
+ if (!frontmatter || !frontmatter.name) {
21
+ return { issue: 'Missing name in hook frontmatter' };
22
+ }
23
+ return null;
24
+ }
25
+ },
26
+ missing_description: {
27
+ id: 'missing_description',
28
+ certainty: 'HIGH',
29
+ check(frontmatter) {
30
+ if (!frontmatter || !frontmatter.description) {
31
+ return { issue: 'Missing description in hook frontmatter' };
32
+ }
33
+ return null;
34
+ }
35
+ }
36
+ };
37
+
38
+ module.exports = {
39
+ hookPatterns
40
+ };
@@ -0,0 +1,127 @@
1
+ const pluginAnalyzer = require('./plugin-analyzer');
2
+ const pluginPatterns = require('./plugin-patterns');
3
+ const toolPatterns = require('./tool-patterns');
4
+ const securityPatterns = require('./security-patterns');
5
+ const agentAnalyzer = require('./agent-analyzer');
6
+ const agentPatterns = require('./agent-patterns');
7
+ const docsAnalyzer = require('./docs-analyzer');
8
+ const docsPatterns = require('./docs-patterns');
9
+ const projectmemoryAnalyzer = require('./projectmemory-analyzer');
10
+ const projectmemoryPatterns = require('./projectmemory-patterns');
11
+ const promptAnalyzer = require('./prompt-analyzer');
12
+ const promptPatterns = require('./prompt-patterns');
13
+ const hookAnalyzer = require('./hook-analyzer');
14
+ const skillAnalyzer = require('./skill-analyzer');
15
+ const crossFileAnalyzer = require('./cross-file-analyzer');
16
+ const crossFilePatterns = require('./cross-file-patterns');
17
+ const reporter = require('./reporter');
18
+ const fixer = require('./fixer');
19
+ const suppression = require('./suppression');
20
+ const autoSuppression = require('./auto-suppression');
21
+ const benchmark = require('./benchmark');
22
+
23
+ module.exports = {
24
+ // Main analyzers
25
+ pluginAnalyzer,
26
+ agentAnalyzer,
27
+ docsAnalyzer,
28
+ projectmemoryAnalyzer,
29
+ promptAnalyzer,
30
+ hookAnalyzer,
31
+ skillAnalyzer,
32
+ crossFileAnalyzer,
33
+
34
+ // Pattern modules
35
+ pluginPatterns,
36
+ toolPatterns,
37
+ securityPatterns,
38
+ agentPatterns,
39
+ docsPatterns,
40
+ projectmemoryPatterns,
41
+ promptPatterns,
42
+ crossFilePatterns,
43
+
44
+ // Output modules
45
+ reporter,
46
+ fixer,
47
+ suppression,
48
+ autoSuppression,
49
+ benchmark,
50
+
51
+ // Convenience exports - Plugin
52
+ analyze: pluginAnalyzer.analyze,
53
+ analyzePlugin: pluginAnalyzer.analyzePlugin,
54
+ analyzeAllPlugins: pluginAnalyzer.analyzeAllPlugins,
55
+ applyFixes: pluginAnalyzer.applyFixes,
56
+ generateReport: pluginAnalyzer.generateReport,
57
+
58
+ // Convenience exports - Agent
59
+ analyzeAgent: agentAnalyzer.analyzeAgent,
60
+ analyzeAllAgents: agentAnalyzer.analyzeAllAgents,
61
+ agentApplyFixes: agentAnalyzer.applyFixes,
62
+ agentGenerateReport: agentAnalyzer.generateReport,
63
+
64
+ // Convenience exports - Docs
65
+ analyzeDoc: docsAnalyzer.analyzeDoc,
66
+ analyzeAllDocs: docsAnalyzer.analyzeAllDocs,
67
+ docsApplyFixes: docsAnalyzer.applyFixes,
68
+ docsGenerateReport: docsAnalyzer.generateReport,
69
+
70
+ // Convenience exports - Project Memory (CLAUDE.md/AGENTS.md)
71
+ analyzeProjectMemory: projectmemoryAnalyzer.analyze,
72
+ analyzeClaudeMd: projectmemoryAnalyzer.analyze, // Alias for familiarity
73
+ findProjectMemoryFile: projectmemoryAnalyzer.findProjectMemoryFile,
74
+ projectMemoryApplyFixes: projectmemoryAnalyzer.applyFixes,
75
+ projectMemoryGenerateReport: projectmemoryAnalyzer.generateReport,
76
+
77
+ // Convenience exports - Prompt
78
+ analyzePrompt: promptAnalyzer.analyzePrompt,
79
+ analyzeAllPrompts: promptAnalyzer.analyzeAllPrompts,
80
+ promptApplyFixes: promptAnalyzer.applyFixes,
81
+ promptGenerateReport: promptAnalyzer.generateReport,
82
+
83
+ // Convenience exports - Hooks
84
+ analyzeHook: hookAnalyzer.analyzeHook,
85
+ analyzeAllHooks: hookAnalyzer.analyzeAllHooks,
86
+ hooksAnalyze: hookAnalyzer.analyze,
87
+
88
+ // Convenience exports - Skills
89
+ analyzeSkill: skillAnalyzer.analyzeSkill,
90
+ analyzeAllSkills: skillAnalyzer.analyzeAllSkills,
91
+ skillsAnalyze: skillAnalyzer.analyze,
92
+
93
+ // Convenience exports - Cross-File Analysis
94
+ analyzeCrossFile: crossFileAnalyzer.analyze,
95
+ analyzeToolConsistency: crossFileAnalyzer.analyzeToolConsistency,
96
+ analyzeWorkflowCompleteness: crossFileAnalyzer.analyzeWorkflowCompleteness,
97
+ analyzePromptConsistency: crossFileAnalyzer.analyzePromptConsistency,
98
+ analyzeSkillAlignment: crossFileAnalyzer.analyzeSkillAlignment,
99
+ loadKnownTools: crossFilePatterns.loadKnownTools,
100
+
101
+ // Convenience exports - Orchestrator
102
+ generateOrchestratorReport: reporter.generateOrchestratorReport,
103
+ deduplicateOrchestratorFindings: reporter.deduplicateOrchestratorFindings,
104
+
105
+ // Convenience exports - Suppression
106
+ loadSuppressionConfig: suppression.loadConfig,
107
+ filterFindings: suppression.filterFindings,
108
+ extractInlineSuppressions: suppression.extractInlineSuppressions,
109
+ generateSuppressionSummary: suppression.generateSuppressionSummary,
110
+
111
+ // Convenience exports - Auto-Suppression
112
+ isLikelyFalsePositive: autoSuppression.isLikelyFalsePositive,
113
+ getProjectId: autoSuppression.getProjectId,
114
+ loadAutoSuppressions: autoSuppression.loadAutoSuppressions,
115
+ saveAutoSuppressions: autoSuppression.saveAutoSuppressions,
116
+ clearAutoSuppressions: autoSuppression.clearAutoSuppressions,
117
+ mergeSuppressions: autoSuppression.mergeSuppressions,
118
+ analyzeForAutoSuppression: autoSuppression.analyzeForAutoSuppression,
119
+ exportAutoSuppressions: autoSuppression.exportAutoSuppressions,
120
+ importAutoSuppressions: autoSuppression.importAutoSuppressions,
121
+
122
+ // Convenience exports - Benchmark
123
+ runPatternBenchmarks: benchmark.runPatternBenchmarks,
124
+ runFixBenchmarks: benchmark.runFixBenchmarks,
125
+ generateBenchmarkReport: benchmark.generateReport,
126
+ assertBenchmarkThresholds: benchmark.assertThresholds
127
+ };
@@ -0,0 +1,402 @@
1
+ /**
2
+ * Plugin Analyzer
3
+ * Main orchestrator for plugin structure and tool use analysis
4
+ *
5
+ * @author Avi Fenesh
6
+ * @license MIT
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+ const pluginPatterns = require('./plugin-patterns');
12
+ const toolPatterns = require('./tool-patterns');
13
+ const securityPatterns = require('./security-patterns');
14
+ const reporter = require('./reporter');
15
+ const fixer = require('./fixer');
16
+
17
+ /**
18
+ * Find nearest package.json by walking up directory tree
19
+ * @param {string} startPath - Starting directory path
20
+ * @param {number} maxLevels - Maximum levels to traverse (default: 5)
21
+ * @returns {string|null} Path to package.json or null if not found
22
+ */
23
+ function findNearestPackageJson(startPath, maxLevels = 5) {
24
+ let currentPath = path.resolve(startPath);
25
+
26
+ for (let i = 0; i < maxLevels; i++) {
27
+ const packageJsonPath = path.join(currentPath, 'package.json');
28
+ if (fs.existsSync(packageJsonPath)) {
29
+ return packageJsonPath;
30
+ }
31
+
32
+ const parentPath = path.dirname(currentPath);
33
+ if (parentPath === currentPath) {
34
+ // Reached root
35
+ break;
36
+ }
37
+ currentPath = parentPath;
38
+ }
39
+
40
+ return null;
41
+ }
42
+
43
+ /**
44
+ * Analyze a single plugin
45
+ * @param {string} pluginPath - Path to plugin directory
46
+ * @param {Object} options - Analysis options
47
+ * @param {boolean} options.verbose - Include LOW certainty issues
48
+ * @returns {Object} Analysis results
49
+ */
50
+ async function analyzePlugin(pluginPath, options = {}) {
51
+ const results = {
52
+ pluginName: path.basename(pluginPath),
53
+ pluginPath,
54
+ filesScanned: 0,
55
+ toolIssues: [],
56
+ structureIssues: [],
57
+ securityIssues: []
58
+ };
59
+
60
+ // Find plugin.json
61
+ const pluginJsonPath = path.join(pluginPath, '.claude-plugin', 'plugin.json');
62
+ const altPluginJsonPath = path.join(pluginPath, 'plugin.json');
63
+
64
+ let pluginJson = null;
65
+ let pluginJsonFile = null;
66
+
67
+ if (fs.existsSync(pluginJsonPath)) {
68
+ try {
69
+ pluginJson = JSON.parse(fs.readFileSync(pluginJsonPath, 'utf8'));
70
+ pluginJsonFile = pluginJsonPath;
71
+ results.filesScanned++;
72
+ } catch (err) {
73
+ results.structureIssues.push({
74
+ issue: 'Failed to parse plugin.json',
75
+ file: pluginJsonPath,
76
+ detail: err.message,
77
+ certainty: 'HIGH',
78
+ patternId: 'malformed_plugin_json'
79
+ });
80
+ }
81
+ } else if (fs.existsSync(altPluginJsonPath)) {
82
+ try {
83
+ pluginJson = JSON.parse(fs.readFileSync(altPluginJsonPath, 'utf8'));
84
+ pluginJsonFile = altPluginJsonPath;
85
+ results.filesScanned++;
86
+ } catch (err) {
87
+ results.structureIssues.push({
88
+ issue: 'Failed to parse plugin.json',
89
+ file: altPluginJsonPath,
90
+ detail: err.message,
91
+ certainty: 'HIGH',
92
+ patternId: 'malformed_plugin_json'
93
+ });
94
+ }
95
+ }
96
+
97
+ // Check package.json for version comparison (walk up to find it)
98
+ const packageJsonPath = findNearestPackageJson(pluginPath);
99
+ let packageJson = null;
100
+ if (packageJsonPath) {
101
+ try {
102
+ packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
103
+ } catch (err) {
104
+ // Non-critical - version comparison will just be skipped
105
+ }
106
+ }
107
+
108
+ // Analyze plugin.json structure
109
+ if (pluginJson) {
110
+ results.pluginName = pluginJson.name || results.pluginName;
111
+
112
+ // Check required fields
113
+ const reqFieldsPattern = pluginPatterns.pluginPatterns.missing_required_plugin_fields;
114
+ const reqResult = reqFieldsPattern.check(pluginJson);
115
+ if (reqResult) {
116
+ results.structureIssues.push({
117
+ ...reqResult,
118
+ file: pluginJsonFile,
119
+ certainty: reqFieldsPattern.certainty,
120
+ patternId: reqFieldsPattern.id
121
+ });
122
+ }
123
+
124
+ // Check version format
125
+ const versionPattern = pluginPatterns.pluginPatterns.invalid_version_format;
126
+ const versionResult = versionPattern.check(pluginJson);
127
+ if (versionResult) {
128
+ results.structureIssues.push({
129
+ ...versionResult,
130
+ file: pluginJsonFile,
131
+ certainty: versionPattern.certainty,
132
+ patternId: versionPattern.id
133
+ });
134
+ }
135
+
136
+ // Check version mismatch
137
+ if (packageJson) {
138
+ const mismatchPattern = pluginPatterns.pluginPatterns.version_mismatch;
139
+ const mismatchResult = mismatchPattern.check(pluginJson, packageJson);
140
+ if (mismatchResult) {
141
+ results.structureIssues.push({
142
+ ...mismatchResult,
143
+ file: pluginJsonFile,
144
+ filePath: pluginJsonFile,
145
+ certainty: mismatchPattern.certainty,
146
+ patternId: mismatchPattern.id,
147
+ autoFixFn: (pj) => fixer.fixVersionMismatch(pj, packageJson.version)
148
+ });
149
+ }
150
+ }
151
+
152
+ // Check tool overexposure
153
+ const overexposurePattern = pluginPatterns.pluginPatterns.tool_overexposure;
154
+ const overexposureResult = overexposurePattern.check(pluginJson);
155
+ if (overexposureResult && (options.verbose || overexposurePattern.certainty !== 'LOW')) {
156
+ results.structureIssues.push({
157
+ ...overexposureResult,
158
+ file: pluginJsonFile,
159
+ certainty: overexposurePattern.certainty,
160
+ patternId: overexposurePattern.id
161
+ });
162
+ }
163
+
164
+ // Analyze commands
165
+ if (pluginJson.commands) {
166
+ for (let idx = 0; idx < pluginJson.commands.length; idx++) {
167
+ const cmd = pluginJson.commands[idx];
168
+ const cmdIssues = analyzeCommand(cmd, pluginJsonFile, idx);
169
+ results.toolIssues.push(...cmdIssues);
170
+ }
171
+ }
172
+ }
173
+
174
+ // Analyze agent files
175
+ const agentsDir = path.join(pluginPath, 'agents');
176
+ if (fs.existsSync(agentsDir)) {
177
+ const agentFiles = fs.readdirSync(agentsDir).filter(f => f.endsWith('.md'));
178
+
179
+ for (const agentFile of agentFiles) {
180
+ const agentPath = path.join(agentsDir, agentFile);
181
+ const content = fs.readFileSync(agentPath, 'utf8');
182
+ results.filesScanned++;
183
+
184
+ // Security checks
185
+ const secIssues = securityPatterns.checkSecurity(content, agentPath);
186
+ results.securityIssues.push(...secIssues.map(i => ({
187
+ ...i,
188
+ file: agentPath
189
+ })));
190
+ }
191
+ }
192
+
193
+ // Analyze command files
194
+ const commandsDir = path.join(pluginPath, 'commands');
195
+ if (fs.existsSync(commandsDir)) {
196
+ const commandFiles = fs.readdirSync(commandsDir).filter(f => f.endsWith('.md'));
197
+
198
+ for (const cmdFile of commandFiles) {
199
+ const cmdPath = path.join(commandsDir, cmdFile);
200
+ const content = fs.readFileSync(cmdPath, 'utf8');
201
+ results.filesScanned++;
202
+
203
+ // Security checks
204
+ const secIssues = securityPatterns.checkSecurity(content, cmdPath);
205
+ results.securityIssues.push(...secIssues.map(i => ({
206
+ ...i,
207
+ file: cmdPath
208
+ })));
209
+ }
210
+ }
211
+
212
+ return results;
213
+ }
214
+
215
+ /**
216
+ * Analyze a command definition
217
+ * @private
218
+ * @param {Object} cmd - Command definition
219
+ * @param {string} filePath - Path to plugin.json
220
+ * @param {number} cmdIndex - Index of command in commands array
221
+ */
222
+ function analyzeCommand(cmd, filePath, cmdIndex) {
223
+ const issues = [];
224
+
225
+ // Check description
226
+ const descPattern = pluginPatterns.pluginPatterns.missing_tool_description;
227
+ const descResult = descPattern.check(cmd);
228
+ if (descResult) {
229
+ issues.push({
230
+ ...descResult,
231
+ tool: cmd.name,
232
+ file: filePath,
233
+ certainty: descPattern.certainty,
234
+ patternId: descPattern.id
235
+ });
236
+ }
237
+
238
+ // Check parameters schema
239
+ if (cmd.parameters) {
240
+ // Missing additionalProperties
241
+ const addPropsPattern = pluginPatterns.pluginPatterns.missing_additional_properties;
242
+ const addPropsResult = addPropsPattern.check(cmd.parameters);
243
+ if (addPropsResult) {
244
+ issues.push({
245
+ ...addPropsResult,
246
+ tool: cmd.name,
247
+ file: filePath,
248
+ filePath: filePath,
249
+ schemaPath: `commands[${cmdIndex}].parameters`,
250
+ certainty: addPropsPattern.certainty,
251
+ patternId: addPropsPattern.id,
252
+ autoFixFn: fixer.fixAdditionalProperties
253
+ });
254
+ }
255
+
256
+ // Missing required
257
+ const reqPattern = pluginPatterns.pluginPatterns.missing_required_fields;
258
+ const reqResult = reqPattern.check(cmd.parameters);
259
+ if (reqResult) {
260
+ issues.push({
261
+ ...reqResult,
262
+ tool: cmd.name,
263
+ file: filePath,
264
+ filePath: filePath,
265
+ schemaPath: `commands[${cmdIndex}].parameters`,
266
+ certainty: reqPattern.certainty,
267
+ patternId: reqPattern.id,
268
+ autoFixFn: fixer.fixRequiredFields
269
+ });
270
+ }
271
+
272
+ // Deep nesting
273
+ const nestPattern = pluginPatterns.pluginPatterns.deep_nesting;
274
+ const nestResult = nestPattern.check(cmd.parameters);
275
+ if (nestResult) {
276
+ issues.push({
277
+ ...nestResult,
278
+ tool: cmd.name,
279
+ file: filePath,
280
+ certainty: nestPattern.certainty,
281
+ patternId: nestPattern.id
282
+ });
283
+ }
284
+
285
+ // Run tool pattern checks
286
+ const toolIssues = toolPatterns.analyzeTool({
287
+ name: cmd.name,
288
+ description: cmd.description,
289
+ inputSchema: cmd.parameters
290
+ });
291
+ issues.push(...toolIssues.map(i => ({
292
+ ...i,
293
+ file: filePath
294
+ })));
295
+ }
296
+
297
+ return issues;
298
+ }
299
+
300
+ /**
301
+ * Analyze all plugins in a directory
302
+ * @param {string} pluginsDir - Path to plugins directory
303
+ * @param {Object} options - Analysis options
304
+ * @returns {Array} Array of analysis results
305
+ */
306
+ async function analyzeAllPlugins(pluginsDir, options = {}) {
307
+ const results = [];
308
+
309
+ if (!fs.existsSync(pluginsDir)) {
310
+ return results;
311
+ }
312
+
313
+ const pluginDirs = fs.readdirSync(pluginsDir, { withFileTypes: true })
314
+ .filter(d => d.isDirectory())
315
+ .map(d => d.name);
316
+
317
+ for (const pluginName of pluginDirs) {
318
+ const pluginPath = path.join(pluginsDir, pluginName);
319
+ const result = await analyzePlugin(pluginPath, options);
320
+ results.push(result);
321
+ }
322
+
323
+ return results;
324
+ }
325
+
326
+ /**
327
+ * Main analyze function
328
+ * @param {Object} options - Analysis options
329
+ * @param {string} options.plugin - Specific plugin name (optional)
330
+ * @param {string} options.pluginsDir - Path to plugins directory
331
+ * @param {boolean} options.verbose - Include LOW certainty issues
332
+ * @returns {Object} Analysis results
333
+ */
334
+ async function analyze(options = {}) {
335
+ const {
336
+ plugin,
337
+ pluginsDir = 'plugins',
338
+ verbose = false
339
+ } = options;
340
+
341
+ if (plugin) {
342
+ // Analyze single plugin
343
+ const pluginPath = path.join(pluginsDir, plugin);
344
+ return analyzePlugin(pluginPath, { verbose });
345
+ } else {
346
+ // Analyze all plugins
347
+ return analyzeAllPlugins(pluginsDir, { verbose });
348
+ }
349
+ }
350
+
351
+ /**
352
+ * Apply fixes to analysis results
353
+ * @param {Object|Array} results - Analysis results
354
+ * @param {Object} options - Fix options
355
+ * @returns {Object} Fix results
356
+ */
357
+ async function applyFixes(results, options = {}) {
358
+ // Collect all issues
359
+ let allIssues = [];
360
+
361
+ if (Array.isArray(results)) {
362
+ for (const r of results) {
363
+ allIssues.push(...(r.toolIssues || []));
364
+ allIssues.push(...(r.structureIssues || []));
365
+ allIssues.push(...(r.securityIssues || []));
366
+ }
367
+ } else {
368
+ allIssues.push(...(results.toolIssues || []));
369
+ allIssues.push(...(results.structureIssues || []));
370
+ allIssues.push(...(results.securityIssues || []));
371
+ }
372
+
373
+ return fixer.applyFixes(allIssues, options);
374
+ }
375
+
376
+ /**
377
+ * Generate report from analysis results
378
+ * @param {Object|Array} results - Analysis results
379
+ * @param {Object} options - Report options
380
+ * @returns {string} Markdown report
381
+ */
382
+ function generateReport(results, options = {}) {
383
+ if (Array.isArray(results)) {
384
+ return reporter.generateSummaryReport(results, options);
385
+ } else {
386
+ return reporter.generateReport(results, options);
387
+ }
388
+ }
389
+
390
+ module.exports = {
391
+ analyze,
392
+ analyzePlugin,
393
+ analyzeAllPlugins,
394
+ applyFixes,
395
+ generateReport,
396
+ // Re-export sub-modules
397
+ pluginPatterns: pluginPatterns.pluginPatterns,
398
+ toolPatterns: toolPatterns.toolPatterns,
399
+ securityPatterns: securityPatterns.securityPatterns,
400
+ reporter,
401
+ fixer
402
+ };