agentsys 5.0.3 → 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 +18 -0
  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 +132 -57
  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 +122 -30
  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 +133 -57
  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 +33 -23
  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 +122 -29
  112. package/plugins/consult/commands/consult.md +135 -58
  113. package/plugins/consult/skills/consult/SKILL.md +31 -20
  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,539 @@
1
+ /**
2
+ * Cross-Platform Best Practices Library
3
+ *
4
+ * Patterns and utilities for building tools that work across:
5
+ * - Claude Code (Anthropic)
6
+ * - OpenCode (multi-model)
7
+ * - Codex CLI (OpenAI)
8
+ *
9
+ * Based on research from official documentation:
10
+ * - Anthropic Claude 4 Best Practices
11
+ * - OpenCode CLI Documentation
12
+ * - Codex CLI Skills and MCP Integration
13
+ * - MCP Specification (2025-11-25)
14
+ *
15
+ * @module cross-platform
16
+ */
17
+
18
+ const path = require('path');
19
+ const fs = require('fs');
20
+ const os = require('os');
21
+
22
+ /**
23
+ * Compare semver strings (e.g., "3.9.0" vs "3.10.0")
24
+ * @param {string} a - First version
25
+ * @param {string} b - Second version
26
+ * @returns {number} -1 if a < b, 1 if a > b, 0 if equal
27
+ */
28
+ function compareSemver(a, b) {
29
+ const partsA = a.split('.').map(n => parseInt(n, 10) || 0);
30
+ const partsB = b.split('.').map(n => parseInt(n, 10) || 0);
31
+
32
+ for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
33
+ const numA = partsA[i] || 0;
34
+ const numB = partsB[i] || 0;
35
+ if (numA < numB) return -1;
36
+ if (numA > numB) return 1;
37
+ }
38
+ return 0;
39
+ }
40
+
41
+ /**
42
+ * Platform detection and configuration
43
+ */
44
+ const PLATFORMS = {
45
+ CLAUDE_CODE: 'claude-code',
46
+ OPENCODE: 'opencode',
47
+ CODEX_CLI: 'codex-cli'
48
+ };
49
+
50
+ /**
51
+ * State directory by platform
52
+ * Each platform uses its own directory to avoid conflicts
53
+ */
54
+ const STATE_DIRS = {
55
+ [PLATFORMS.CLAUDE_CODE]: '.claude',
56
+ [PLATFORMS.OPENCODE]: '.opencode',
57
+ [PLATFORMS.CODEX_CLI]: '.codex'
58
+ };
59
+
60
+ /**
61
+ * Get the state directory for the current platform
62
+ * Uses AI_STATE_DIR env var if set, otherwise defaults to .claude
63
+ *
64
+ * @returns {string} State directory name
65
+ */
66
+ function getStateDir() {
67
+ return process.env.AI_STATE_DIR || STATE_DIRS[PLATFORMS.CLAUDE_CODE];
68
+ }
69
+
70
+ /**
71
+ * Detect current platform from environment
72
+ *
73
+ * @returns {string} Platform identifier
74
+ */
75
+ function detectPlatform() {
76
+ const stateDir = process.env.AI_STATE_DIR;
77
+ if (stateDir === '.opencode') return PLATFORMS.OPENCODE;
78
+ if (stateDir === '.codex') return PLATFORMS.CODEX_CLI;
79
+ return PLATFORMS.CLAUDE_CODE;
80
+ }
81
+
82
+ /**
83
+ * Get plugin root directory (works across all platforms)
84
+ *
85
+ * Search order:
86
+ * 1. PLUGIN_ROOT env var (MCP mode)
87
+ * 2. Search plugin installation directories
88
+ *
89
+ * @param {string} pluginName - Plugin name (e.g., 'enhance')
90
+ * @returns {string} Plugin root path or null if not found
91
+ */
92
+ function getPluginRoot(pluginName = 'enhance') {
93
+ // Try environment variable first (MCP mode)
94
+ if (process.env.PLUGIN_ROOT) {
95
+ return process.env.PLUGIN_ROOT;
96
+ }
97
+
98
+ // Try to find in plugin cache
99
+ const stateDir = getStateDir();
100
+ const home = os.homedir();
101
+
102
+ // Search pattern: ~/.{stateDir}/plugins/cache/agentsys/{pluginName}/{version}
103
+ const searchPaths = [
104
+ path.join(home, stateDir, 'plugins', 'cache', 'agentsys', pluginName),
105
+ path.join(home, stateDir, 'plugins', 'agentsys', pluginName)
106
+ ];
107
+
108
+ for (const searchPath of searchPaths) {
109
+ if (fs.existsSync(searchPath)) {
110
+ // Find latest version directory
111
+ const versions = fs.readdirSync(searchPath).filter(v => {
112
+ return fs.statSync(path.join(searchPath, v)).isDirectory();
113
+ });
114
+
115
+ if (versions.length > 0) {
116
+ // Sort by semver and take latest
117
+ const latest = versions.sort(compareSemver).reverse()[0];
118
+ return path.join(searchPath, latest);
119
+ }
120
+ }
121
+ }
122
+
123
+ return null;
124
+ }
125
+
126
+ /**
127
+ * Get path to enhance suppressions file
128
+ *
129
+ * @returns {string} Path to suppressions.json in state directory
130
+ */
131
+ function getSuppressionPath() {
132
+ const stateDir = getStateDir();
133
+ const home = os.homedir();
134
+ return path.join(home, stateDir, 'enhance', 'suppressions.json');
135
+ }
136
+
137
+ /**
138
+ * MCP Tool Schema Best Practices
139
+ *
140
+ * Guidelines for cross-platform tool definitions:
141
+ * 1. Use descriptive, semantic names (workflow_status not ws)
142
+ * 2. Keep descriptions concise (<100 chars) for token efficiency
143
+ * 3. Use flat parameter structures when possible
144
+ * 4. Include enums for constrained values
145
+ * 5. Make parameters optional with sensible defaults
146
+ */
147
+ const TOOL_SCHEMA_GUIDELINES = {
148
+ // Max description length for token efficiency
149
+ maxDescriptionLength: 100,
150
+
151
+ // Naming conventions
152
+ namingPattern: /^[a-z][a-z0-9_]*$/,
153
+
154
+ // Parameter best practices
155
+ preferFlatStructures: true,
156
+ useEnumsForConstraints: true,
157
+ documentDefaults: true
158
+ };
159
+
160
+ /**
161
+ * Create a tool definition following cross-platform best practices
162
+ *
163
+ * @param {string} name - Tool name (snake_case)
164
+ * @param {string} description - Concise description
165
+ * @param {Object} properties - Input schema properties
166
+ * @param {string[]} required - Required property names
167
+ * @returns {Object} MCP-compatible tool definition
168
+ */
169
+ function createToolDefinition(name, description, properties = {}, required = []) {
170
+ // Validate name
171
+ if (!TOOL_SCHEMA_GUIDELINES.namingPattern.test(name)) {
172
+ console.warn(`Tool name "${name}" should be snake_case`);
173
+ }
174
+
175
+ // Warn if description too long
176
+ if (description.length > TOOL_SCHEMA_GUIDELINES.maxDescriptionLength) {
177
+ console.warn(`Tool "${name}" description exceeds ${TOOL_SCHEMA_GUIDELINES.maxDescriptionLength} chars`);
178
+ }
179
+
180
+ return {
181
+ name,
182
+ description,
183
+ inputSchema: {
184
+ type: 'object',
185
+ properties,
186
+ required
187
+ }
188
+ };
189
+ }
190
+
191
+ /**
192
+ * Error Response Patterns
193
+ *
194
+ * MCP uses isError flag for application errors, NOT JSON-RPC error codes.
195
+ * Error messages should be actionable so AI can recover.
196
+ */
197
+
198
+ /**
199
+ * Create a success response
200
+ *
201
+ * @param {*} data - Response data (will be JSON stringified if object)
202
+ * @returns {Object} MCP content response
203
+ */
204
+ function successResponse(data) {
205
+ const text = typeof data === 'object' ? JSON.stringify(data, null, 2) : String(data);
206
+ return {
207
+ content: [{ type: 'text', text }]
208
+ };
209
+ }
210
+
211
+ /**
212
+ * Create an error response with actionable message
213
+ *
214
+ * @param {string} message - Error message (should suggest recovery)
215
+ * @param {Object} details - Optional additional details
216
+ * @returns {Object} MCP error response
217
+ */
218
+ function errorResponse(message, details = null) {
219
+ let text = `Error: ${message}`;
220
+ if (details) {
221
+ text += `\nDetails: ${JSON.stringify(details)}`;
222
+ }
223
+ return {
224
+ content: [{ type: 'text', text }],
225
+ isError: true
226
+ };
227
+ }
228
+
229
+ /**
230
+ * Create an error response for missing tool
231
+ *
232
+ * @param {string} name - Tool name that was requested
233
+ * @param {string[]} available - List of available tools
234
+ * @returns {Object} MCP error response
235
+ */
236
+ function unknownToolResponse(name, available = []) {
237
+ let text = `Error: Unknown tool "${name}"`;
238
+ if (available.length > 0) {
239
+ text += `\nAvailable tools: ${available.join(', ')}`;
240
+ }
241
+ return {
242
+ content: [{ type: 'text', text }],
243
+ isError: true
244
+ };
245
+ }
246
+
247
+ /**
248
+ * Prompt Formatting for Cross-Model Compatibility
249
+ *
250
+ * Different models have different preferences:
251
+ * - Claude: Trained with XML tags, follows instructions literally
252
+ * - GPT-4: Prefers Markdown, more flexible interpretation
253
+ *
254
+ * For maximum compatibility, use both:
255
+ * - Markdown headers for major sections
256
+ * - XML tags for data blocks
257
+ */
258
+
259
+ /**
260
+ * Format structured data for cross-model prompts
261
+ *
262
+ * @param {string} tag - XML-style tag name
263
+ * @param {string} content - Content to wrap
264
+ * @returns {string} Formatted content block
265
+ */
266
+ function formatBlock(tag, content) {
267
+ return `<${tag}>\n${content}\n</${tag}>`;
268
+ }
269
+
270
+ /**
271
+ * Format a list of items for prompts
272
+ *
273
+ * @param {string[]} items - Items to format
274
+ * @param {boolean} numbered - Use numbered list
275
+ * @returns {string} Formatted list
276
+ */
277
+ function formatList(items, numbered = false) {
278
+ return items.map((item, i) => {
279
+ const prefix = numbered ? `${i + 1}.` : '-';
280
+ return `${prefix} ${item}`;
281
+ }).join('\n');
282
+ }
283
+
284
+ /**
285
+ * Create an agent prompt section with cross-model formatting
286
+ *
287
+ * @param {string} title - Section title
288
+ * @param {string} content - Section content
289
+ * @returns {string} Formatted section
290
+ */
291
+ function formatSection(title, content) {
292
+ return `## ${title}\n\n${content}\n`;
293
+ }
294
+
295
+ /**
296
+ * Token Efficiency Strategies
297
+ *
298
+ * Key insights from research:
299
+ * - MCP tools can consume 50K+ tokens before conversation starts
300
+ * - Concise descriptions reduce overhead by 60%+
301
+ * - Consolidate similar tools (one tool with filter vs many tools)
302
+ * - Return minimal structured JSON, not verbose text
303
+ */
304
+
305
+ /**
306
+ * Truncate text to limit with ellipsis
307
+ *
308
+ * @param {string} text - Text to truncate
309
+ * @param {number} maxLength - Maximum length
310
+ * @returns {string} Truncated text
311
+ */
312
+ function truncate(text, maxLength) {
313
+ if (text.length <= maxLength) return text;
314
+ return text.substring(0, maxLength - 3) + '...';
315
+ }
316
+
317
+ /**
318
+ * Create a compact summary of findings/results
319
+ *
320
+ * @param {Array} items - Items to summarize
321
+ * @param {Function} keyFn - Function to extract key from item
322
+ * @param {number} maxItems - Maximum items to include
323
+ * @returns {Object} Compact summary
324
+ */
325
+ function compactSummary(items, keyFn, maxItems = 10) {
326
+ const limited = items.slice(0, maxItems);
327
+ const truncated = items.length > maxItems;
328
+
329
+ // Group by key
330
+ const groups = {};
331
+ for (const item of limited) {
332
+ const key = keyFn(item);
333
+ groups[key] = (groups[key] || 0) + 1;
334
+ }
335
+
336
+ return {
337
+ total: items.length,
338
+ showing: limited.length,
339
+ truncated,
340
+ byKey: groups
341
+ };
342
+ }
343
+
344
+ /**
345
+ * Agent Prompt Best Practices
346
+ *
347
+ * Cross-model recommendations:
348
+ * 1. State instructions explicitly - don't rely on inference
349
+ * 2. Put critical constraints at START and END (Lost in Middle)
350
+ * 3. Use imperative language: "Do X", "Never Y"
351
+ * 4. Include 2-3 examples for complex tasks
352
+ * 5. Explicit tool allowlisting
353
+ * 6. Flat state management - pass state each turn
354
+ */
355
+
356
+ /**
357
+ * Agent prompt template structure
358
+ */
359
+ const AGENT_TEMPLATE = `# Agent: {name}
360
+
361
+ ## Role
362
+ {role}
363
+
364
+ ## Instructions
365
+ {instructions}
366
+
367
+ ## Tools Available
368
+ {tools}
369
+ If a tool is not listed above, respond with: "Tool not available"
370
+
371
+ ## Output Format
372
+ {outputFormat}
373
+
374
+ ## Critical Constraints
375
+ {constraints}`;
376
+
377
+ /**
378
+ * Create an agent prompt from template
379
+ *
380
+ * @param {Object} config - Agent configuration
381
+ * @param {string} config.name - Agent name
382
+ * @param {string} config.role - One-sentence role description
383
+ * @param {string[]} config.instructions - Imperative instructions
384
+ * @param {Object[]} config.tools - Available tools {name, description}
385
+ * @param {string} config.outputFormat - Expected output format
386
+ * @param {string[]} config.constraints - Critical constraints (repeated for emphasis)
387
+ * @returns {string} Formatted agent prompt
388
+ */
389
+ function createAgentPrompt(config) {
390
+ const {
391
+ name,
392
+ role,
393
+ instructions = [],
394
+ tools = [],
395
+ outputFormat = 'Respond with structured JSON',
396
+ constraints = []
397
+ } = config;
398
+
399
+ // Format instructions as numbered list
400
+ const instructionsList = instructions.map((inst, i) => `${i + 1}. ${inst}`).join('\n');
401
+
402
+ // Format tools
403
+ const toolsList = tools.map(t => `- ${t.name}: ${t.description}`).join('\n');
404
+
405
+ // Format constraints (repeated for "Lost in Middle" mitigation)
406
+ const constraintsList = constraints.map(c => `- **${c}**`).join('\n');
407
+
408
+ return AGENT_TEMPLATE
409
+ .replace('{name}', name)
410
+ .replace('{role}', role)
411
+ .replace('{instructions}', instructionsList)
412
+ .replace('{tools}', toolsList)
413
+ .replace('{outputFormat}', outputFormat)
414
+ .replace('{constraints}', constraintsList);
415
+ }
416
+
417
+ /**
418
+ * Convert a path to forward slashes (safe for require() on all platforms)
419
+ * Windows paths with backslashes break in require() strings
420
+ *
421
+ * @param {string} p - Path to normalize
422
+ * @returns {string} Path with forward slashes
423
+ */
424
+ function normalizePathForRequire(p) {
425
+ return p.replace(/\\/g, '/');
426
+ }
427
+
428
+ /**
429
+ * Platform-specific configuration helpers
430
+ */
431
+
432
+ /**
433
+ * Get OpenCode MCP configuration object
434
+ *
435
+ * @param {string} serverPath - Path to MCP server
436
+ * @param {Object} env - Environment variables
437
+ * @returns {Object} OpenCode config structure
438
+ */
439
+ function getOpenCodeConfig(serverPath, env = {}) {
440
+ return {
441
+ mcp: {
442
+ 'agentsys': {
443
+ type: 'local',
444
+ command: ['node', serverPath],
445
+ environment: {
446
+ PLUGIN_ROOT: path.dirname(path.dirname(serverPath)),
447
+ AI_STATE_DIR: '.opencode',
448
+ ...env
449
+ },
450
+ timeout: 10000,
451
+ enabled: true
452
+ }
453
+ }
454
+ };
455
+ }
456
+
457
+ /**
458
+ * Get Codex CLI MCP configuration (TOML format)
459
+ *
460
+ * @param {string} serverPath - Path to MCP server
461
+ * @param {Object} env - Environment variables
462
+ * @returns {string} TOML configuration
463
+ */
464
+ function getCodexConfig(serverPath, env = {}) {
465
+ const envEntries = Object.entries({
466
+ PLUGIN_ROOT: path.dirname(path.dirname(serverPath)),
467
+ AI_STATE_DIR: '.codex',
468
+ ...env
469
+ }).map(([k, v]) => `${k} = "${v}"`).join(', ');
470
+
471
+ return `
472
+ [mcp_servers.agentsys]
473
+ command = "node"
474
+ args = ["${serverPath}"]
475
+ env = { ${envEntries} }
476
+ enabled = true
477
+ `.trim();
478
+ }
479
+
480
+ /**
481
+ * Instruction file conventions by platform
482
+ */
483
+ const INSTRUCTION_FILES = {
484
+ [PLATFORMS.CLAUDE_CODE]: ['CLAUDE.md', '.claude/CLAUDE.md'],
485
+ [PLATFORMS.OPENCODE]: ['AGENTS.md', 'CLAUDE.md'],
486
+ [PLATFORMS.CODEX_CLI]: ['AGENTS.md', 'AGENTS.override.md']
487
+ };
488
+
489
+ /**
490
+ * Get instruction file paths for current platform
491
+ *
492
+ * @param {string} platform - Platform identifier
493
+ * @returns {string[]} Instruction file paths in precedence order
494
+ */
495
+ function getInstructionFiles(platform = null) {
496
+ const p = platform || detectPlatform();
497
+ return INSTRUCTION_FILES[p] || INSTRUCTION_FILES[PLATFORMS.CLAUDE_CODE];
498
+ }
499
+
500
+ module.exports = {
501
+ // Platform detection
502
+ PLATFORMS,
503
+ STATE_DIRS,
504
+ getStateDir,
505
+ detectPlatform,
506
+ getPluginRoot,
507
+ getSuppressionPath,
508
+
509
+ // Tool schema
510
+ TOOL_SCHEMA_GUIDELINES,
511
+ createToolDefinition,
512
+
513
+ // Response helpers
514
+ successResponse,
515
+ errorResponse,
516
+ unknownToolResponse,
517
+
518
+ // Prompt formatting
519
+ formatBlock,
520
+ formatList,
521
+ formatSection,
522
+
523
+ // Token efficiency
524
+ truncate,
525
+ compactSummary,
526
+
527
+ // Agent prompts
528
+ AGENT_TEMPLATE,
529
+ createAgentPrompt,
530
+
531
+ // Platform configs
532
+ getOpenCodeConfig,
533
+ getCodexConfig,
534
+ getInstructionFiles,
535
+ INSTRUCTION_FILES,
536
+
537
+ // Path normalization
538
+ normalizePathForRequire
539
+ };