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,352 @@
1
+ /**
2
+ * Plugin Discovery Module
3
+ *
4
+ * Convention-based filesystem scanning to discover plugins, commands,
5
+ * agents, and skills. Replaces all hardcoded registration lists.
6
+ *
7
+ * Convention:
8
+ * - plugins/<name>/.claude-plugin/plugin.json -> plugin
9
+ * - plugins/<name>/commands/*.md -> commands
10
+ * - plugins/<name>/agents/*.md -> agents
11
+ * - plugins/<name>/skills/<skill>/SKILL.md -> skills
12
+ *
13
+ * @module discovery
14
+ * @author Avi Fenesh
15
+ * @license MIT
16
+ */
17
+
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+
21
+ // Module-level cache
22
+ let _cache = null;
23
+ let _cacheRoot = null;
24
+
25
+ /**
26
+ * Parse YAML frontmatter from a markdown file's content.
27
+ * Returns an object of key-value pairs from the frontmatter block.
28
+ *
29
+ * @param {string} content - File content
30
+ * @returns {Object} Parsed frontmatter key-value pairs
31
+ */
32
+ function parseFrontmatter(content) {
33
+ if (!content || !content.startsWith('---')) {
34
+ return {};
35
+ }
36
+ const endIdx = content.indexOf('\n---', 3);
37
+ if (endIdx === -1) {
38
+ return {};
39
+ }
40
+ const frontmatterBlock = content.substring(4, endIdx);
41
+ const result = {};
42
+ const lines = frontmatterBlock.split('\n');
43
+ let currentKey = null;
44
+ let currentArray = null;
45
+
46
+ for (const line of lines) {
47
+ // Check for YAML array item (e.g. " - Read")
48
+ const arrayItemMatch = line.match(/^\s+-\s+(.+)$/);
49
+ if (arrayItemMatch && currentKey && currentArray) {
50
+ let item = arrayItemMatch[1].trim();
51
+ // Strip surrounding quotes from array items
52
+ if ((item.startsWith('"') && item.endsWith('"')) ||
53
+ (item.startsWith("'") && item.endsWith("'"))) {
54
+ item = item.slice(1, -1);
55
+ }
56
+ currentArray.push(item);
57
+ continue;
58
+ }
59
+
60
+ const colonIdx = line.indexOf(':');
61
+ if (colonIdx > 0) {
62
+ // Flush any pending array
63
+ if (currentKey && currentArray) {
64
+ result[currentKey] = currentArray;
65
+ currentKey = null;
66
+ currentArray = null;
67
+ }
68
+
69
+ const key = line.substring(0, colonIdx).trim();
70
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;
71
+ let value = line.substring(colonIdx + 1).trim();
72
+
73
+ if (value === '') {
74
+ // Key with no value - could be start of a YAML array
75
+ currentKey = key;
76
+ currentArray = [];
77
+ } else {
78
+ // Strip surrounding quotes
79
+ if ((value.startsWith('"') && value.endsWith('"')) ||
80
+ (value.startsWith("'") && value.endsWith("'"))) {
81
+ value = value.slice(1, -1);
82
+ }
83
+ result[key] = value;
84
+ currentKey = null;
85
+ currentArray = null;
86
+ }
87
+ }
88
+ }
89
+
90
+ // Flush any trailing array
91
+ if (currentKey && currentArray) {
92
+ result[currentKey] = currentArray;
93
+ }
94
+
95
+ return result;
96
+ }
97
+
98
+ /**
99
+ * Validate a plugin/directory name is safe for filesystem and shell use.
100
+ * Only allows lowercase letters, digits, and hyphens.
101
+ *
102
+ * @param {string} name - Directory name to validate
103
+ * @returns {boolean}
104
+ */
105
+ function isValidPluginName(name) {
106
+ return /^[a-z0-9][a-z0-9-]*$/.test(name);
107
+ }
108
+
109
+ /**
110
+ * Resolve the plugins directory from a repo root.
111
+ *
112
+ * @param {string} [repoRoot] - Repository root path. Defaults to two levels up from this file.
113
+ * @returns {string} Absolute path to plugins/ directory
114
+ */
115
+ function resolvePluginsDir(repoRoot) {
116
+ if (!repoRoot) {
117
+ repoRoot = path.resolve(__dirname, '..', '..');
118
+ }
119
+ return path.join(repoRoot, 'plugins');
120
+ }
121
+
122
+ /**
123
+ * Discover all plugins by scanning plugins/ for directories with .claude-plugin/plugin.json.
124
+ *
125
+ * @param {string} [repoRoot] - Repository root path
126
+ * @returns {string[]} Sorted array of plugin names
127
+ */
128
+ function discoverPlugins(repoRoot) {
129
+ const cached = getCache(repoRoot);
130
+ if (cached && cached.plugins) return cached.plugins;
131
+
132
+ const pluginsDir = resolvePluginsDir(repoRoot);
133
+ if (!fs.existsSync(pluginsDir)) return [];
134
+
135
+ const entries = fs.readdirSync(pluginsDir);
136
+ const plugins = entries.filter(name => {
137
+ if (!isValidPluginName(name)) return false;
138
+ const pluginJson = path.join(pluginsDir, name, '.claude-plugin', 'plugin.json');
139
+ return fs.existsSync(pluginJson);
140
+ }).sort();
141
+
142
+ setCache(repoRoot, 'plugins', plugins);
143
+ return plugins;
144
+ }
145
+
146
+ /**
147
+ * Discover all commands by scanning plugins/<name>/commands/*.md.
148
+ *
149
+ * @param {string} [repoRoot] - Repository root path
150
+ * @returns {Array<{name: string, plugin: string, file: string, frontmatter: Object}>}
151
+ */
152
+ function discoverCommands(repoRoot) {
153
+ const cached = getCache(repoRoot);
154
+ if (cached && cached.commands) return cached.commands;
155
+
156
+ const pluginsDir = resolvePluginsDir(repoRoot);
157
+ const plugins = discoverPlugins(repoRoot);
158
+ const commands = [];
159
+
160
+ for (const plugin of plugins) {
161
+ const commandsDir = path.join(pluginsDir, plugin, 'commands');
162
+ if (!fs.existsSync(commandsDir)) continue;
163
+
164
+ const files = fs.readdirSync(commandsDir).filter(f => f.endsWith('.md')).sort();
165
+ for (const file of files) {
166
+ const filePath = path.join(commandsDir, file);
167
+ const content = fs.readFileSync(filePath, 'utf8');
168
+ const frontmatter = parseFrontmatter(content);
169
+ commands.push({
170
+ name: file.replace(/\.md$/, ''),
171
+ plugin,
172
+ file,
173
+ frontmatter
174
+ });
175
+ }
176
+ }
177
+
178
+ setCache(repoRoot, 'commands', commands);
179
+ return commands;
180
+ }
181
+
182
+ /**
183
+ * Discover all file-based agents by scanning plugins/<name>/agents/*.md.
184
+ *
185
+ * @param {string} [repoRoot] - Repository root path
186
+ * @returns {Array<{name: string, plugin: string, file: string, frontmatter: Object}>}
187
+ */
188
+ function discoverAgents(repoRoot) {
189
+ const cached = getCache(repoRoot);
190
+ if (cached && cached.agents) return cached.agents;
191
+
192
+ const pluginsDir = resolvePluginsDir(repoRoot);
193
+ const plugins = discoverPlugins(repoRoot);
194
+ const agents = [];
195
+
196
+ for (const plugin of plugins) {
197
+ const agentsDir = path.join(pluginsDir, plugin, 'agents');
198
+ if (!fs.existsSync(agentsDir)) continue;
199
+
200
+ const files = fs.readdirSync(agentsDir).filter(f => f.endsWith('.md')).sort();
201
+ for (const file of files) {
202
+ const filePath = path.join(agentsDir, file);
203
+ const content = fs.readFileSync(filePath, 'utf8');
204
+ const frontmatter = parseFrontmatter(content);
205
+ agents.push({
206
+ name: file.replace(/\.md$/, ''),
207
+ plugin,
208
+ file,
209
+ frontmatter
210
+ });
211
+ }
212
+ }
213
+
214
+ setCache(repoRoot, 'agents', agents);
215
+ return agents;
216
+ }
217
+
218
+ /**
219
+ * Discover all skills by scanning plugins/<name>/skills/<skill>/SKILL.md.
220
+ *
221
+ * @param {string} [repoRoot] - Repository root path
222
+ * @returns {Array<{name: string, plugin: string, dir: string, frontmatter: Object}>}
223
+ */
224
+ function discoverSkills(repoRoot) {
225
+ const cached = getCache(repoRoot);
226
+ if (cached && cached.skills) return cached.skills;
227
+
228
+ const pluginsDir = resolvePluginsDir(repoRoot);
229
+ const plugins = discoverPlugins(repoRoot);
230
+ const skills = [];
231
+
232
+ for (const plugin of plugins) {
233
+ const skillsDir = path.join(pluginsDir, plugin, 'skills');
234
+ if (!fs.existsSync(skillsDir)) continue;
235
+
236
+ const entries = fs.readdirSync(skillsDir).sort();
237
+ for (const entry of entries) {
238
+ const skillFile = path.join(skillsDir, entry, 'SKILL.md');
239
+ if (fs.existsSync(skillFile)) {
240
+ const content = fs.readFileSync(skillFile, 'utf8');
241
+ const frontmatter = parseFrontmatter(content);
242
+ skills.push({
243
+ name: entry,
244
+ plugin,
245
+ dir: entry,
246
+ frontmatter
247
+ });
248
+ }
249
+ }
250
+ }
251
+
252
+ setCache(repoRoot, 'skills', skills);
253
+ return skills;
254
+ }
255
+
256
+ /**
257
+ * Build OpenCode command mappings from discovered commands.
258
+ * Returns [targetFile, pluginName, sourceFile] tuples.
259
+ *
260
+ * @param {string} [repoRoot] - Repository root path
261
+ * @returns {Array<[string, string, string]>}
262
+ */
263
+ function getCommandMappings(repoRoot) {
264
+ const commands = discoverCommands(repoRoot);
265
+ return commands.map(cmd => [cmd.file, cmd.plugin, cmd.file]);
266
+ }
267
+
268
+ /**
269
+ * Build Codex skill mappings from discovered commands.
270
+ * Returns [skillName, pluginName, sourceFile, description] tuples.
271
+ * Uses codex-description frontmatter field, falls back to description.
272
+ *
273
+ * @param {string} [repoRoot] - Repository root path
274
+ * @returns {Array<[string, string, string, string]>}
275
+ */
276
+ function getCodexSkillMappings(repoRoot) {
277
+ const commands = discoverCommands(repoRoot);
278
+ return commands.map(cmd => {
279
+ const description = cmd.frontmatter['codex-description'] ||
280
+ cmd.frontmatter.description ||
281
+ '';
282
+ return [cmd.name, cmd.plugin, cmd.file, description];
283
+ });
284
+ }
285
+
286
+ /**
287
+ * Build a dynamic regex for stripping plugin prefixes from agent references.
288
+ * Example: `next-task:agent-name` -> `agent-name`
289
+ *
290
+ * @param {string} [repoRoot] - Repository root path
291
+ * @returns {RegExp} Regex matching plugin prefix patterns
292
+ */
293
+ function getPluginPrefixRegex(repoRoot) {
294
+ const plugins = discoverPlugins(repoRoot);
295
+ if (plugins.length === 0) return /$^/g; // Matches nothing
296
+ const escaped = plugins.map(p => p.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
297
+ return new RegExp(`(${escaped.join('|')})`, 'g');
298
+ }
299
+
300
+ /**
301
+ * Get all discovery results in a single call.
302
+ *
303
+ * @param {string} [repoRoot] - Repository root path
304
+ * @returns {{plugins: string[], commands: Array, agents: Array, skills: Array}}
305
+ */
306
+ function discoverAll(repoRoot) {
307
+ return {
308
+ plugins: discoverPlugins(repoRoot),
309
+ commands: discoverCommands(repoRoot),
310
+ agents: discoverAgents(repoRoot),
311
+ skills: discoverSkills(repoRoot)
312
+ };
313
+ }
314
+
315
+ // --- Cache helpers ---
316
+
317
+ function getCache(repoRoot) {
318
+ const root = repoRoot || path.resolve(__dirname, '..', '..');
319
+ if (_cache && _cacheRoot === root) return _cache;
320
+ return null;
321
+ }
322
+
323
+ function setCache(repoRoot, key, value) {
324
+ const root = repoRoot || path.resolve(__dirname, '..', '..');
325
+ if (!_cache || _cacheRoot !== root) {
326
+ _cache = {};
327
+ _cacheRoot = root;
328
+ }
329
+ _cache[key] = value;
330
+ }
331
+
332
+ /**
333
+ * Invalidate the module-level cache. Used for testing.
334
+ */
335
+ function invalidateCache() {
336
+ _cache = null;
337
+ _cacheRoot = null;
338
+ }
339
+
340
+ module.exports = {
341
+ parseFrontmatter,
342
+ isValidPluginName,
343
+ discoverPlugins,
344
+ discoverCommands,
345
+ discoverAgents,
346
+ discoverSkills,
347
+ discoverAll,
348
+ getCommandMappings,
349
+ getCodexSkillMappings,
350
+ getPluginPrefixRegex,
351
+ invalidateCache
352
+ };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Reality Check Data Collectors
3
+ * Pure JavaScript data collection - no LLM needed
4
+ *
5
+ * BACKWARD COMPATIBILITY: This module re-exports from lib/collectors.
6
+ * For new code, use: const { collectors } = require('@agentsys/lib');
7
+ *
8
+ * Replaces three LLM agents (issue-scanner, doc-analyzer, code-explorer)
9
+ * with deterministic JavaScript functions.
10
+ *
11
+ * @module lib/drift-detect/collectors
12
+ */
13
+
14
+ 'use strict';
15
+
16
+ // Re-export from shared collectors module
17
+ const collectors = require('../collectors');
18
+
19
+ // Legacy DEFAULT_OPTIONS (backward compatible format)
20
+ const DEFAULT_OPTIONS = {
21
+ sources: ['github', 'docs', 'code'],
22
+ depth: 'thorough',
23
+ issueLimit: collectors.github.DEFAULT_OPTIONS.issueLimit,
24
+ prLimit: collectors.github.DEFAULT_OPTIONS.prLimit,
25
+ timeout: collectors.github.DEFAULT_OPTIONS.timeout
26
+ };
27
+
28
+ // Re-export all functions for backward compatibility
29
+ module.exports = {
30
+ DEFAULT_OPTIONS,
31
+ scanGitHubState: collectors.scanGitHubState,
32
+ analyzeDocumentation: collectors.analyzeDocumentation,
33
+ scanCodebase: collectors.scanCodebase,
34
+ collectAllData: collectors.collectAllData,
35
+ isGhAvailable: collectors.isGhAvailable,
36
+ isPathSafe: collectors.documentation.isPathSafe
37
+ };