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,457 @@
1
+ /**
2
+ * Prompt Analyzer
3
+ * Analyzes general prompts for prompt engineering best practices
4
+ *
5
+ * @author Avi Fenesh
6
+ * @license MIT
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+ const { promptPatterns, estimateTokens, extractCodeBlocks } = require('./prompt-patterns');
12
+ const reporter = require('./reporter');
13
+
14
+ /**
15
+ * Detect prompt file type from path or content
16
+ * @param {string} filePath - File path
17
+ * @param {string} content - File content
18
+ * @returns {string} File type: 'agent', 'command', 'skill', 'prompt', 'markdown'
19
+ */
20
+ function detectPromptType(filePath, content) {
21
+ const lowerPath = filePath.toLowerCase();
22
+
23
+ // Check path patterns
24
+ if (lowerPath.includes('/agents/') || lowerPath.includes('\\agents\\')) {
25
+ return 'agent';
26
+ }
27
+ if (lowerPath.includes('/commands/') || lowerPath.includes('\\commands\\')) {
28
+ return 'command';
29
+ }
30
+ if (lowerPath.includes('/skills/') || lowerPath.includes('\\skills\\')) {
31
+ return 'skill';
32
+ }
33
+ if (lowerPath.includes('/prompts/') || lowerPath.includes('\\prompts\\')) {
34
+ return 'prompt';
35
+ }
36
+
37
+ // Check content patterns
38
+ if (content) {
39
+ // Agent frontmatter
40
+ if (/^---\s*\nname:\s*\w+/m.test(content)) {
41
+ return 'agent';
42
+ }
43
+ // System prompt indicators
44
+ if (/<system>/i.test(content) || /^##?\s*system\s+prompt/im.test(content)) {
45
+ return 'prompt';
46
+ }
47
+ }
48
+
49
+ return 'markdown';
50
+ }
51
+
52
+ /**
53
+ * Analyze a single prompt file
54
+ * @param {string} promptPath - Path to prompt file
55
+ * @param {Object} options - Analysis options
56
+ * @param {boolean} options.verbose - Include LOW certainty issues
57
+ * @returns {Object} Analysis results
58
+ */
59
+ function analyzePrompt(promptPath, options = {}) {
60
+ const { verbose = false } = options;
61
+
62
+ const results = {
63
+ promptName: path.basename(promptPath, path.extname(promptPath)),
64
+ promptPath,
65
+ promptType: null,
66
+ tokenCount: 0,
67
+ clarityIssues: [],
68
+ structureIssues: [],
69
+ exampleIssues: [],
70
+ contextIssues: [],
71
+ outputIssues: [],
72
+ antiPatternIssues: [],
73
+ codeValidationIssues: []
74
+ };
75
+
76
+ // Read file
77
+ if (!fs.existsSync(promptPath)) {
78
+ results.structureIssues.push({
79
+ issue: 'File not found',
80
+ file: promptPath,
81
+ certainty: 'HIGH',
82
+ patternId: 'file_not_found'
83
+ });
84
+ return results;
85
+ }
86
+
87
+ let content;
88
+ try {
89
+ content = fs.readFileSync(promptPath, 'utf8');
90
+ } catch (err) {
91
+ results.structureIssues.push({
92
+ issue: `Failed to read file: ${err.message}`,
93
+ file: promptPath,
94
+ certainty: 'HIGH',
95
+ patternId: 'read_error'
96
+ });
97
+ return results;
98
+ }
99
+
100
+ // Detect prompt type
101
+ results.promptType = detectPromptType(promptPath, content);
102
+
103
+ // Calculate token count
104
+ results.tokenCount = estimateTokens(content);
105
+
106
+ // Strip bad example sections before analysis
107
+ // These intentionally show anti-patterns and should not be flagged
108
+ const BAD_EXAMPLE_TAG_PATTERN = /<bad[_\- ]?example>[\s\S]*?<\/bad[_\- ]?example>/gi;
109
+ const BAD_EXAMPLE_CODE_PATTERN = /```[^\n]*bad[^\n]*\n[\s\S]*?```/gi;
110
+ const contentForAnalysis = content
111
+ .replace(BAD_EXAMPLE_TAG_PATTERN, '')
112
+ .replace(BAD_EXAMPLE_CODE_PATTERN, '');
113
+
114
+ // Run each pattern check
115
+ for (const pattern of Object.values(promptPatterns)) {
116
+ // Skip LOW certainty unless verbose
117
+ if (pattern.certainty === 'LOW' && !verbose) {
118
+ continue;
119
+ }
120
+
121
+ // Run the check on content with bad examples stripped
122
+ // Pass file path for patterns that need path-based filtering
123
+ const result = pattern.check(contentForAnalysis, promptPath);
124
+
125
+ if (result) {
126
+ const issue = {
127
+ ...result,
128
+ file: promptPath,
129
+ certainty: pattern.certainty,
130
+ patternId: pattern.id,
131
+ autoFix: pattern.autoFix
132
+ };
133
+
134
+ // Route to appropriate issue category
135
+ switch (pattern.category) {
136
+ case 'clarity':
137
+ results.clarityIssues.push(issue);
138
+ break;
139
+ case 'structure':
140
+ results.structureIssues.push(issue);
141
+ break;
142
+ case 'examples':
143
+ results.exampleIssues.push(issue);
144
+ break;
145
+ case 'context':
146
+ results.contextIssues.push(issue);
147
+ break;
148
+ case 'output':
149
+ results.outputIssues.push(issue);
150
+ break;
151
+ case 'anti-pattern':
152
+ results.antiPatternIssues.push(issue);
153
+ break;
154
+ case 'code-validation':
155
+ results.codeValidationIssues.push(issue);
156
+ break;
157
+ default:
158
+ results.structureIssues.push(issue);
159
+ }
160
+ }
161
+ }
162
+
163
+ return results;
164
+ }
165
+
166
+ /**
167
+ * Analyze all prompts in a directory
168
+ * @param {string} promptsDir - Path to prompts directory
169
+ * @param {Object} options - Analysis options
170
+ * @returns {Array} Array of analysis results
171
+ */
172
+ function analyzeAllPrompts(promptsDir, options = {}) {
173
+ const { recursive = true, extensions = ['.md', '.txt'], ...analyzeOptions } = options;
174
+ const results = [];
175
+
176
+ // Validate and normalize path
177
+ if (!promptsDir || typeof promptsDir !== 'string') {
178
+ return results;
179
+ }
180
+
181
+ // Resolve to absolute path to prevent path traversal
182
+ const resolvedDir = path.resolve(promptsDir);
183
+
184
+ if (!fs.existsSync(resolvedDir)) {
185
+ return results;
186
+ }
187
+
188
+ // Collect prompt files
189
+ const promptFiles = [];
190
+
191
+ function findPromptFiles(dir) {
192
+ let entries;
193
+ try {
194
+ entries = fs.readdirSync(dir, { withFileTypes: true });
195
+ } catch (err) {
196
+ return;
197
+ }
198
+
199
+ for (const entry of entries) {
200
+ const fullPath = path.join(dir, entry.name);
201
+
202
+ // Ensure traversed paths stay within the resolved directory
203
+ // Use path.relative() for Windows case-insensitive path comparison
204
+ const resolvedFullPath = path.resolve(fullPath);
205
+ const relativePath = path.relative(resolvedDir, resolvedFullPath);
206
+ if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
207
+ continue;
208
+ }
209
+
210
+ if (entry.isDirectory() && recursive) {
211
+ // Skip common non-prompt directories
212
+ if (!['node_modules', '.git', 'dist', 'build', 'tests', '__tests__'].includes(entry.name)) {
213
+ findPromptFiles(fullPath);
214
+ }
215
+ } else if (entry.isFile()) {
216
+ const ext = path.extname(entry.name).toLowerCase();
217
+ if (extensions.includes(ext)) {
218
+ // Skip README files
219
+ if (entry.name.toLowerCase() !== 'readme.md') {
220
+ promptFiles.push(fullPath);
221
+ }
222
+ }
223
+ }
224
+ }
225
+ }
226
+
227
+ findPromptFiles(resolvedDir);
228
+
229
+ // Analyze each file
230
+ for (const promptFile of promptFiles) {
231
+ const result = analyzePrompt(promptFile, analyzeOptions);
232
+ results.push(result);
233
+ }
234
+
235
+ return results;
236
+ }
237
+
238
+ /**
239
+ * Main analyze function
240
+ * @param {Object} options - Analysis options
241
+ * @param {string} options.prompt - Specific prompt file path (optional)
242
+ * @param {string} options.promptsDir - Path to prompts directory
243
+ * @param {boolean} options.verbose - Include LOW certainty issues
244
+ * @returns {Object|Array} Analysis results
245
+ */
246
+ function analyze(options = {}) {
247
+ const {
248
+ prompt,
249
+ promptsDir,
250
+ verbose = false
251
+ } = options;
252
+
253
+ if (prompt) {
254
+ // Check if prompt is a directory or file
255
+ try {
256
+ const stats = fs.statSync(prompt);
257
+ if (stats.isDirectory()) {
258
+ return analyzeAllPrompts(prompt, { verbose });
259
+ } else {
260
+ return analyzePrompt(prompt, { verbose });
261
+ }
262
+ } catch (err) {
263
+ // If doesn't exist, let analyzePrompt handle the error
264
+ return analyzePrompt(prompt, { verbose });
265
+ }
266
+ } else if (promptsDir) {
267
+ return analyzeAllPrompts(promptsDir, { verbose });
268
+ } else {
269
+ // Default: analyze common prompt locations
270
+ const defaultDirs = ['prompts', 'agents', 'commands', 'skills'];
271
+ const allResults = [];
272
+
273
+ for (const dir of defaultDirs) {
274
+ if (fs.existsSync(dir)) {
275
+ const results = analyzeAllPrompts(dir, { verbose });
276
+ allResults.push(...results);
277
+ }
278
+ }
279
+
280
+ return allResults.length > 0 ? allResults : [];
281
+ }
282
+ }
283
+
284
+ /**
285
+ * Apply fixes to analysis results
286
+ * Currently only aggressive_emphasis is auto-fixable
287
+ * @param {Object|Array} results - Analysis results
288
+ * @param {Object} options - Fix options
289
+ * @returns {Object} Fix results
290
+ */
291
+ function applyFixes(results, options = {}) {
292
+ const { dryRun = false, backup = true } = options;
293
+
294
+ const fixResults = {
295
+ applied: [],
296
+ skipped: [],
297
+ errors: []
298
+ };
299
+
300
+ // Collect all issues
301
+ let allIssues = [];
302
+
303
+ if (Array.isArray(results)) {
304
+ for (const r of results) {
305
+ allIssues.push(...(r.clarityIssues || []));
306
+ allIssues.push(...(r.structureIssues || []));
307
+ allIssues.push(...(r.exampleIssues || []));
308
+ allIssues.push(...(r.contextIssues || []));
309
+ allIssues.push(...(r.outputIssues || []));
310
+ allIssues.push(...(r.antiPatternIssues || []));
311
+ allIssues.push(...(r.codeValidationIssues || []));
312
+ }
313
+ } else {
314
+ allIssues.push(...(results.clarityIssues || []));
315
+ allIssues.push(...(results.structureIssues || []));
316
+ allIssues.push(...(results.exampleIssues || []));
317
+ allIssues.push(...(results.contextIssues || []));
318
+ allIssues.push(...(results.outputIssues || []));
319
+ allIssues.push(...(results.antiPatternIssues || []));
320
+ allIssues.push(...(results.codeValidationIssues || []));
321
+ }
322
+
323
+ // Filter to auto-fixable HIGH certainty issues
324
+ const fixableIssues = allIssues.filter(i =>
325
+ i.certainty === 'HIGH' && i.autoFix
326
+ );
327
+
328
+ // Group by file
329
+ const byFile = new Map();
330
+ for (const issue of fixableIssues) {
331
+ const fp = issue.file;
332
+ if (!byFile.has(fp)) {
333
+ byFile.set(fp, []);
334
+ }
335
+ byFile.get(fp).push(issue);
336
+ }
337
+
338
+ // Process each file
339
+ for (const [filePath, fileIssues] of byFile) {
340
+ try {
341
+ if (!fs.existsSync(filePath)) {
342
+ fixResults.errors.push({ filePath, error: 'File not found' });
343
+ continue;
344
+ }
345
+
346
+ let content = fs.readFileSync(filePath, 'utf8');
347
+ const appliedToFile = [];
348
+
349
+ for (const issue of fileIssues) {
350
+ try {
351
+ if (issue.patternId === 'aggressive_emphasis') {
352
+ content = fixAggressiveEmphasis(content);
353
+ appliedToFile.push({
354
+ issue: issue.issue,
355
+ fix: 'Reduced aggressive emphasis',
356
+ filePath
357
+ });
358
+ }
359
+ // Add more fixers as needed
360
+ } catch (err) {
361
+ fixResults.errors.push({
362
+ issue: issue.issue,
363
+ filePath,
364
+ error: err.message
365
+ });
366
+ }
367
+ }
368
+
369
+ // Write changes
370
+ if (!dryRun && appliedToFile.length > 0) {
371
+ if (backup) {
372
+ fs.writeFileSync(`${filePath}.backup`, fs.readFileSync(filePath, 'utf8'), 'utf8');
373
+ }
374
+ fs.writeFileSync(filePath, content, 'utf8');
375
+ }
376
+
377
+ fixResults.applied.push(...appliedToFile);
378
+
379
+ } catch (err) {
380
+ fixResults.errors.push({
381
+ filePath,
382
+ error: err.message
383
+ });
384
+ }
385
+ }
386
+
387
+ return fixResults;
388
+ }
389
+
390
+ /**
391
+ * Fix aggressive emphasis in content
392
+ * @param {string} content - Content to fix
393
+ * @returns {string} Fixed content
394
+ */
395
+ function fixAggressiveEmphasis(content) {
396
+ if (!content) return content;
397
+
398
+ // Replace aggressive CAPS phrases with normal case
399
+ // Note: These should align with words detected by aggressive_emphasis pattern
400
+ const replacements = [
401
+ { pattern: /\bCRITICAL\b/g, replacement: 'critical' },
402
+ { pattern: /\bIMPORTANT\b/g, replacement: 'important' },
403
+ { pattern: /\bMUST\b/g, replacement: 'must' },
404
+ { pattern: /\bNEVER\b/g, replacement: 'never' },
405
+ { pattern: /\bALWAYS\b/g, replacement: 'always' },
406
+ { pattern: /\bREQUIRED\b/g, replacement: 'required' },
407
+ { pattern: /\bMANDATORY\b/g, replacement: 'mandatory' },
408
+ { pattern: /\bESSENTIAL\b/g, replacement: 'essential' },
409
+ { pattern: /\bWARNING\b/g, replacement: 'warning' },
410
+ { pattern: /\bCAUTION\b/g, replacement: 'caution' },
411
+ // Additional aggressive words detected by pattern
412
+ { pattern: /\bABSOLUTELY\b/g, replacement: 'absolutely' },
413
+ { pattern: /\bTOTALLY\b/g, replacement: 'totally' },
414
+ { pattern: /\bEXTREMELY\b/g, replacement: 'extremely' },
415
+ { pattern: /\bDEFINITELY\b/g, replacement: 'definitely' },
416
+ { pattern: /\bCOMPLETELY\b/g, replacement: 'completely' },
417
+ { pattern: /\bENTIRELY\b/g, replacement: 'entirely' },
418
+ { pattern: /\bFORBIDDEN\b/g, replacement: 'forbidden' },
419
+ { pattern: /\bURGENT\b/g, replacement: 'urgent' }
420
+ ];
421
+
422
+ let result = content;
423
+ for (const { pattern, replacement } of replacements) {
424
+ result = result.replace(pattern, replacement);
425
+ }
426
+
427
+ // Reduce multiple exclamation marks
428
+ result = result.replace(/!{2,}/g, '!');
429
+
430
+ return result;
431
+ }
432
+
433
+ /**
434
+ * Generate report from analysis results
435
+ * @param {Object|Array} results - Analysis results
436
+ * @param {Object} options - Report options
437
+ * @returns {string} Markdown report
438
+ */
439
+ function generateReport(results, options = {}) {
440
+ if (Array.isArray(results)) {
441
+ return reporter.generatePromptSummaryReport(results, options);
442
+ } else {
443
+ return reporter.generatePromptReport(results, options);
444
+ }
445
+ }
446
+
447
+ module.exports = {
448
+ analyzePrompt,
449
+ analyzeAllPrompts,
450
+ analyze,
451
+ applyFixes,
452
+ fixAggressiveEmphasis,
453
+ generateReport,
454
+ detectPromptType,
455
+ estimateTokens,
456
+ extractCodeBlocks
457
+ };