agentsys 5.0.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 (1310) hide show
  1. package/.agnix.toml +49 -0
  2. package/.claude-plugin/marketplace.json +110 -0
  3. package/.claude-plugin/plugin.json +20 -0
  4. package/AGENTS.md +260 -0
  5. package/CHANGELOG.md +190 -0
  6. package/LICENSE +21 -0
  7. package/README.md +916 -0
  8. package/SECURITY.md +45 -0
  9. package/adapters/README.md +258 -0
  10. package/adapters/codex/README.md +273 -0
  11. package/adapters/codex/install.sh +260 -0
  12. package/adapters/codex/skills/agnix/SKILL.md +138 -0
  13. package/adapters/codex/skills/audit-project/SKILL.md +334 -0
  14. package/adapters/codex/skills/audit-project-agents/SKILL.md +459 -0
  15. package/adapters/codex/skills/audit-project-github/SKILL.md +146 -0
  16. package/adapters/codex/skills/consult/SKILL.md +245 -0
  17. package/adapters/codex/skills/delivery-approval/SKILL.md +339 -0
  18. package/adapters/codex/skills/deslop/SKILL.md +167 -0
  19. package/adapters/codex/skills/drift-detect/SKILL.md +268 -0
  20. package/adapters/codex/skills/enhance/SKILL.md +177 -0
  21. package/adapters/codex/skills/learn/SKILL.md +188 -0
  22. package/adapters/codex/skills/next-task/SKILL.md +546 -0
  23. package/adapters/codex/skills/perf/SKILL.md +469 -0
  24. package/adapters/codex/skills/repo-map/SKILL.md +132 -0
  25. package/adapters/codex/skills/ship/SKILL.md +491 -0
  26. package/adapters/codex/skills/ship-ci-review-loop/SKILL.md +473 -0
  27. package/adapters/codex/skills/ship-deployment/SKILL.md +336 -0
  28. package/adapters/codex/skills/ship-error-handling/SKILL.md +260 -0
  29. package/adapters/codex/skills/sync-docs/SKILL.md +186 -0
  30. package/adapters/opencode/README.md +302 -0
  31. package/adapters/opencode/agents/agent-enhancer.md +65 -0
  32. package/adapters/opencode/agents/agnix-agent.md +56 -0
  33. package/adapters/opencode/agents/ci-fixer.md +104 -0
  34. package/adapters/opencode/agents/ci-monitor.md +127 -0
  35. package/adapters/opencode/agents/claudemd-enhancer.md +66 -0
  36. package/adapters/opencode/agents/consult-agent.md +124 -0
  37. package/adapters/opencode/agents/cross-file-enhancer.md +54 -0
  38. package/adapters/opencode/agents/delivery-validator.md +115 -0
  39. package/adapters/opencode/agents/deslop-agent.md +88 -0
  40. package/adapters/opencode/agents/docs-enhancer.md +65 -0
  41. package/adapters/opencode/agents/exploration-agent.md +143 -0
  42. package/adapters/opencode/agents/hooks-enhancer.md +66 -0
  43. package/adapters/opencode/agents/implementation-agent.md +206 -0
  44. package/adapters/opencode/agents/learn-agent.md +279 -0
  45. package/adapters/opencode/agents/map-validator.md +65 -0
  46. package/adapters/opencode/agents/perf-analyzer.md +40 -0
  47. package/adapters/opencode/agents/perf-code-paths.md +12 -0
  48. package/adapters/opencode/agents/perf-investigation-logger.md +44 -0
  49. package/adapters/opencode/agents/perf-orchestrator.md +147 -0
  50. package/adapters/opencode/agents/perf-theory-gatherer.md +18 -0
  51. package/adapters/opencode/agents/perf-theory-tester.md +43 -0
  52. package/adapters/opencode/agents/plan-synthesizer.md +229 -0
  53. package/adapters/opencode/agents/planning-agent.md +235 -0
  54. package/adapters/opencode/agents/plugin-enhancer.md +64 -0
  55. package/adapters/opencode/agents/prompt-enhancer.md +58 -0
  56. package/adapters/opencode/agents/simple-fixer.md +107 -0
  57. package/adapters/opencode/agents/skills-enhancer.md +66 -0
  58. package/adapters/opencode/agents/sync-docs-agent.md +153 -0
  59. package/adapters/opencode/agents/task-discoverer.md +80 -0
  60. package/adapters/opencode/agents/test-coverage-checker.md +144 -0
  61. package/adapters/opencode/agents/worktree-manager.md +209 -0
  62. package/adapters/opencode/commands/agnix.md +106 -0
  63. package/adapters/opencode/commands/audit-project-agents.md +125 -0
  64. package/adapters/opencode/commands/audit-project-github.md +145 -0
  65. package/adapters/opencode/commands/audit-project.md +268 -0
  66. package/adapters/opencode/commands/consult.md +252 -0
  67. package/adapters/opencode/commands/delivery-approval.md +212 -0
  68. package/adapters/opencode/commands/deslop.md +132 -0
  69. package/adapters/opencode/commands/drift-detect.md +173 -0
  70. package/adapters/opencode/commands/enhance.md +183 -0
  71. package/adapters/opencode/commands/learn.md +116 -0
  72. package/adapters/opencode/commands/next-task.md +393 -0
  73. package/adapters/opencode/commands/perf.md +49 -0
  74. package/adapters/opencode/commands/repo-map.md +69 -0
  75. package/adapters/opencode/commands/ship-ci-review-loop.md +334 -0
  76. package/adapters/opencode/commands/ship-deployment.md +336 -0
  77. package/adapters/opencode/commands/ship-error-handling.md +248 -0
  78. package/adapters/opencode/commands/ship.md +371 -0
  79. package/adapters/opencode/commands/sync-docs.md +108 -0
  80. package/adapters/opencode/install.sh +322 -0
  81. package/adapters/opencode/skills/agnix/SKILL.md +139 -0
  82. package/adapters/opencode/skills/consult/SKILL.md +292 -0
  83. package/adapters/opencode/skills/deslop/SKILL.md +169 -0
  84. package/adapters/opencode/skills/discover-tasks/SKILL.md +102 -0
  85. package/adapters/opencode/skills/drift-analysis/SKILL.md +279 -0
  86. package/adapters/opencode/skills/enhance-agent-prompts/SKILL.md +279 -0
  87. package/adapters/opencode/skills/enhance-claude-memory/SKILL.md +390 -0
  88. package/adapters/opencode/skills/enhance-cross-file/SKILL.md +112 -0
  89. package/adapters/opencode/skills/enhance-docs/SKILL.md +288 -0
  90. package/adapters/opencode/skills/enhance-hooks/SKILL.md +557 -0
  91. package/adapters/opencode/skills/enhance-orchestrator/SKILL.md +114 -0
  92. package/adapters/opencode/skills/enhance-plugins/SKILL.md +314 -0
  93. package/adapters/opencode/skills/enhance-prompts/SKILL.md +341 -0
  94. package/adapters/opencode/skills/enhance-skills/SKILL.md +443 -0
  95. package/adapters/opencode/skills/learn/SKILL.md +352 -0
  96. package/adapters/opencode/skills/orchestrate-review/SKILL.md +95 -0
  97. package/adapters/opencode/skills/perf-analyzer/SKILL.md +38 -0
  98. package/adapters/opencode/skills/perf-baseline-manager/SKILL.md +31 -0
  99. package/adapters/opencode/skills/perf-benchmarker/SKILL.md +49 -0
  100. package/adapters/opencode/skills/perf-code-paths/SKILL.md +33 -0
  101. package/adapters/opencode/skills/perf-investigation-logger/SKILL.md +42 -0
  102. package/adapters/opencode/skills/perf-profiler/SKILL.md +39 -0
  103. package/adapters/opencode/skills/perf-theory-gatherer/SKILL.md +36 -0
  104. package/adapters/opencode/skills/perf-theory-tester/SKILL.md +37 -0
  105. package/adapters/opencode/skills/repo-mapping/SKILL.md +86 -0
  106. package/adapters/opencode/skills/sync-docs/SKILL.md +246 -0
  107. package/adapters/opencode/skills/validate-delivery/SKILL.md +112 -0
  108. package/adapters/opencode-plugin/index.ts +346 -0
  109. package/adapters/opencode-plugin/package.json +21 -0
  110. package/agent-knowledge/AGENTS.md +62 -0
  111. package/agent-knowledge/ai-cli-advanced-integration-patterns.md +670 -0
  112. package/agent-knowledge/ai-cli-non-interactive-programmatic-usage.md +1394 -0
  113. package/agent-knowledge/resources/ai-cli-non-interactive-programmatic-usage-sources.json +500 -0
  114. package/bin/cli.js +719 -0
  115. package/bin/dev-cli.js +587 -0
  116. package/lib/adapter-transforms.js +278 -0
  117. package/lib/collectors/codebase.js +392 -0
  118. package/lib/collectors/docs-patterns.js +713 -0
  119. package/lib/collectors/documentation.js +219 -0
  120. package/lib/collectors/github.js +266 -0
  121. package/lib/collectors/index.js +126 -0
  122. package/lib/config/index.js +14 -0
  123. package/lib/cross-platform/index.js +539 -0
  124. package/lib/discovery/index.js +352 -0
  125. package/lib/drift-detect/collectors.js +37 -0
  126. package/lib/enhance/agent-analyzer.js +421 -0
  127. package/lib/enhance/agent-patterns.js +571 -0
  128. package/lib/enhance/auto-suppression.js +622 -0
  129. package/lib/enhance/benchmark.js +417 -0
  130. package/lib/enhance/cross-file-analyzer.js +930 -0
  131. package/lib/enhance/cross-file-patterns.js +370 -0
  132. package/lib/enhance/docs-analyzer.js +325 -0
  133. package/lib/enhance/docs-patterns.js +671 -0
  134. package/lib/enhance/fixer.js +721 -0
  135. package/lib/enhance/hook-analyzer.js +135 -0
  136. package/lib/enhance/hook-patterns.js +40 -0
  137. package/lib/enhance/index.js +127 -0
  138. package/lib/enhance/plugin-analyzer.js +402 -0
  139. package/lib/enhance/plugin-patterns.js +326 -0
  140. package/lib/enhance/projectmemory-analyzer.js +551 -0
  141. package/lib/enhance/projectmemory-patterns.js +617 -0
  142. package/lib/enhance/prompt-analyzer.js +457 -0
  143. package/lib/enhance/prompt-patterns.js +1484 -0
  144. package/lib/enhance/reporter.js +1348 -0
  145. package/lib/enhance/security-patterns.js +284 -0
  146. package/lib/enhance/skill-analyzer.js +182 -0
  147. package/lib/enhance/skill-patterns.js +147 -0
  148. package/lib/enhance/suppression.js +352 -0
  149. package/lib/enhance/tool-patterns.js +373 -0
  150. package/lib/index.js +270 -0
  151. package/lib/package.json +25 -0
  152. package/lib/patterns/cli-enhancers.js +611 -0
  153. package/lib/patterns/pipeline.js +948 -0
  154. package/lib/patterns/review-patterns.js +558 -0
  155. package/lib/patterns/slop-analyzers.js +2305 -0
  156. package/lib/patterns/slop-patterns.js +1187 -0
  157. package/lib/perf/analyzer/index.js +22 -0
  158. package/lib/perf/argument-parser.js +105 -0
  159. package/lib/perf/baseline-comparator.js +50 -0
  160. package/lib/perf/baseline-store.js +127 -0
  161. package/lib/perf/benchmark-runner.js +399 -0
  162. package/lib/perf/breaking-point-finder.js +52 -0
  163. package/lib/perf/breaking-point-runner.js +60 -0
  164. package/lib/perf/checkpoint.js +123 -0
  165. package/lib/perf/code-paths.js +86 -0
  166. package/lib/perf/consolidation.js +37 -0
  167. package/lib/perf/constraint-runner.js +71 -0
  168. package/lib/perf/experiment-runner.js +32 -0
  169. package/lib/perf/index.js +41 -0
  170. package/lib/perf/investigation-state.js +875 -0
  171. package/lib/perf/optimization-runner.js +79 -0
  172. package/lib/perf/profilers/go.js +22 -0
  173. package/lib/perf/profilers/index.js +46 -0
  174. package/lib/perf/profilers/java.js +23 -0
  175. package/lib/perf/profilers/node.js +27 -0
  176. package/lib/perf/profilers/python.js +23 -0
  177. package/lib/perf/profilers/rust.js +23 -0
  178. package/lib/perf/profiling-runner.js +56 -0
  179. package/lib/perf/schemas.js +140 -0
  180. package/lib/platform/detect-platform.js +413 -0
  181. package/lib/platform/detection-configs.js +93 -0
  182. package/lib/platform/state-dir.js +132 -0
  183. package/lib/platform/verify-tools.js +182 -0
  184. package/lib/repo-map/cache.js +152 -0
  185. package/lib/repo-map/index.js +222 -0
  186. package/lib/repo-map/installer.js +212 -0
  187. package/lib/repo-map/queries/go.js +27 -0
  188. package/lib/repo-map/queries/index.js +100 -0
  189. package/lib/repo-map/queries/java.js +38 -0
  190. package/lib/repo-map/queries/javascript.js +55 -0
  191. package/lib/repo-map/queries/python.js +24 -0
  192. package/lib/repo-map/queries/rust.js +73 -0
  193. package/lib/repo-map/queries/typescript.js +38 -0
  194. package/lib/repo-map/runner.js +1165 -0
  195. package/lib/repo-map/updater.js +474 -0
  196. package/lib/repo-map/usage-analyzer.js +407 -0
  197. package/lib/schemas/plugin-manifest.schema.json +57 -0
  198. package/lib/schemas/validator.js +247 -0
  199. package/lib/sources/custom-handler.js +199 -0
  200. package/lib/sources/policy-questions.js +246 -0
  201. package/lib/sources/source-cache.js +165 -0
  202. package/lib/state/workflow-state.js +575 -0
  203. package/lib/types/agent-frontmatter.d.ts +134 -0
  204. package/lib/types/command-frontmatter.d.ts +107 -0
  205. package/lib/types/hook-frontmatter.d.ts +115 -0
  206. package/lib/types/index.d.ts +84 -0
  207. package/lib/types/plugin-manifest.d.ts +102 -0
  208. package/lib/types/skill-frontmatter.d.ts +89 -0
  209. package/lib/utils/atomic-write.js +94 -0
  210. package/lib/utils/cache-manager.js +159 -0
  211. package/lib/utils/context-optimizer.js +300 -0
  212. package/lib/utils/deprecation.js +37 -0
  213. package/lib/utils/shell-escape.js +88 -0
  214. package/meta/skills/maintain-cross-platform/SKILL.md +1022 -0
  215. package/package.json +92 -0
  216. package/plugins/agnix/.claude-plugin/plugin.json +22 -0
  217. package/plugins/agnix/agents/agnix-agent.md +56 -0
  218. package/plugins/agnix/commands/agnix.md +139 -0
  219. package/plugins/agnix/skills/agnix/SKILL.md +138 -0
  220. package/plugins/audit-project/.claude-plugin/plugin.json +20 -0
  221. package/plugins/audit-project/commands/audit-project-agents.md +458 -0
  222. package/plugins/audit-project/commands/audit-project-github.md +144 -0
  223. package/plugins/audit-project/commands/audit-project.md +336 -0
  224. package/plugins/audit-project/lib/adapter-transforms.js +278 -0
  225. package/plugins/audit-project/lib/collectors/codebase.js +392 -0
  226. package/plugins/audit-project/lib/collectors/docs-patterns.js +713 -0
  227. package/plugins/audit-project/lib/collectors/documentation.js +219 -0
  228. package/plugins/audit-project/lib/collectors/github.js +266 -0
  229. package/plugins/audit-project/lib/collectors/index.js +126 -0
  230. package/plugins/audit-project/lib/config/index.js +14 -0
  231. package/plugins/audit-project/lib/cross-platform/index.js +539 -0
  232. package/plugins/audit-project/lib/discovery/index.js +352 -0
  233. package/plugins/audit-project/lib/drift-detect/collectors.js +37 -0
  234. package/plugins/audit-project/lib/enhance/agent-analyzer.js +421 -0
  235. package/plugins/audit-project/lib/enhance/agent-patterns.js +571 -0
  236. package/plugins/audit-project/lib/enhance/auto-suppression.js +622 -0
  237. package/plugins/audit-project/lib/enhance/benchmark.js +417 -0
  238. package/plugins/audit-project/lib/enhance/cross-file-analyzer.js +930 -0
  239. package/plugins/audit-project/lib/enhance/cross-file-patterns.js +370 -0
  240. package/plugins/audit-project/lib/enhance/docs-analyzer.js +325 -0
  241. package/plugins/audit-project/lib/enhance/docs-patterns.js +671 -0
  242. package/plugins/audit-project/lib/enhance/fixer.js +721 -0
  243. package/plugins/audit-project/lib/enhance/hook-analyzer.js +135 -0
  244. package/plugins/audit-project/lib/enhance/hook-patterns.js +40 -0
  245. package/plugins/audit-project/lib/enhance/index.js +127 -0
  246. package/plugins/audit-project/lib/enhance/plugin-analyzer.js +402 -0
  247. package/plugins/audit-project/lib/enhance/plugin-patterns.js +326 -0
  248. package/plugins/audit-project/lib/enhance/projectmemory-analyzer.js +551 -0
  249. package/plugins/audit-project/lib/enhance/projectmemory-patterns.js +617 -0
  250. package/plugins/audit-project/lib/enhance/prompt-analyzer.js +457 -0
  251. package/plugins/audit-project/lib/enhance/prompt-patterns.js +1484 -0
  252. package/plugins/audit-project/lib/enhance/reporter.js +1348 -0
  253. package/plugins/audit-project/lib/enhance/security-patterns.js +284 -0
  254. package/plugins/audit-project/lib/enhance/skill-analyzer.js +182 -0
  255. package/plugins/audit-project/lib/enhance/skill-patterns.js +147 -0
  256. package/plugins/audit-project/lib/enhance/suppression.js +352 -0
  257. package/plugins/audit-project/lib/enhance/tool-patterns.js +373 -0
  258. package/plugins/audit-project/lib/index.js +270 -0
  259. package/plugins/audit-project/lib/patterns/cli-enhancers.js +611 -0
  260. package/plugins/audit-project/lib/patterns/pipeline.js +948 -0
  261. package/plugins/audit-project/lib/patterns/review-patterns.js +558 -0
  262. package/plugins/audit-project/lib/patterns/slop-analyzers.js +2305 -0
  263. package/plugins/audit-project/lib/patterns/slop-patterns.js +1187 -0
  264. package/plugins/audit-project/lib/perf/analyzer/index.js +22 -0
  265. package/plugins/audit-project/lib/perf/argument-parser.js +105 -0
  266. package/plugins/audit-project/lib/perf/baseline-comparator.js +50 -0
  267. package/plugins/audit-project/lib/perf/baseline-store.js +127 -0
  268. package/plugins/audit-project/lib/perf/benchmark-runner.js +399 -0
  269. package/plugins/audit-project/lib/perf/breaking-point-finder.js +52 -0
  270. package/plugins/audit-project/lib/perf/breaking-point-runner.js +60 -0
  271. package/plugins/audit-project/lib/perf/checkpoint.js +123 -0
  272. package/plugins/audit-project/lib/perf/code-paths.js +86 -0
  273. package/plugins/audit-project/lib/perf/consolidation.js +37 -0
  274. package/plugins/audit-project/lib/perf/constraint-runner.js +71 -0
  275. package/plugins/audit-project/lib/perf/experiment-runner.js +32 -0
  276. package/plugins/audit-project/lib/perf/index.js +41 -0
  277. package/plugins/audit-project/lib/perf/investigation-state.js +875 -0
  278. package/plugins/audit-project/lib/perf/optimization-runner.js +79 -0
  279. package/plugins/audit-project/lib/perf/profilers/go.js +22 -0
  280. package/plugins/audit-project/lib/perf/profilers/index.js +46 -0
  281. package/plugins/audit-project/lib/perf/profilers/java.js +23 -0
  282. package/plugins/audit-project/lib/perf/profilers/node.js +27 -0
  283. package/plugins/audit-project/lib/perf/profilers/python.js +23 -0
  284. package/plugins/audit-project/lib/perf/profilers/rust.js +23 -0
  285. package/plugins/audit-project/lib/perf/profiling-runner.js +56 -0
  286. package/plugins/audit-project/lib/perf/schemas.js +140 -0
  287. package/plugins/audit-project/lib/platform/detect-platform.js +413 -0
  288. package/plugins/audit-project/lib/platform/detection-configs.js +93 -0
  289. package/plugins/audit-project/lib/platform/state-dir.js +132 -0
  290. package/plugins/audit-project/lib/platform/verify-tools.js +182 -0
  291. package/plugins/audit-project/lib/repo-map/cache.js +152 -0
  292. package/plugins/audit-project/lib/repo-map/index.js +222 -0
  293. package/plugins/audit-project/lib/repo-map/installer.js +212 -0
  294. package/plugins/audit-project/lib/repo-map/queries/go.js +27 -0
  295. package/plugins/audit-project/lib/repo-map/queries/index.js +100 -0
  296. package/plugins/audit-project/lib/repo-map/queries/java.js +38 -0
  297. package/plugins/audit-project/lib/repo-map/queries/javascript.js +55 -0
  298. package/plugins/audit-project/lib/repo-map/queries/python.js +24 -0
  299. package/plugins/audit-project/lib/repo-map/queries/rust.js +73 -0
  300. package/plugins/audit-project/lib/repo-map/queries/typescript.js +38 -0
  301. package/plugins/audit-project/lib/repo-map/runner.js +1165 -0
  302. package/plugins/audit-project/lib/repo-map/updater.js +474 -0
  303. package/plugins/audit-project/lib/repo-map/usage-analyzer.js +407 -0
  304. package/plugins/audit-project/lib/schemas/plugin-manifest.schema.json +57 -0
  305. package/plugins/audit-project/lib/schemas/validator.js +247 -0
  306. package/plugins/audit-project/lib/sources/custom-handler.js +199 -0
  307. package/plugins/audit-project/lib/sources/policy-questions.js +246 -0
  308. package/plugins/audit-project/lib/sources/source-cache.js +165 -0
  309. package/plugins/audit-project/lib/state/workflow-state.js +575 -0
  310. package/plugins/audit-project/lib/types/agent-frontmatter.d.ts +134 -0
  311. package/plugins/audit-project/lib/types/command-frontmatter.d.ts +107 -0
  312. package/plugins/audit-project/lib/types/hook-frontmatter.d.ts +115 -0
  313. package/plugins/audit-project/lib/types/index.d.ts +84 -0
  314. package/plugins/audit-project/lib/types/plugin-manifest.d.ts +102 -0
  315. package/plugins/audit-project/lib/types/skill-frontmatter.d.ts +89 -0
  316. package/plugins/audit-project/lib/utils/atomic-write.js +94 -0
  317. package/plugins/audit-project/lib/utils/cache-manager.js +159 -0
  318. package/plugins/audit-project/lib/utils/context-optimizer.js +300 -0
  319. package/plugins/audit-project/lib/utils/deprecation.js +37 -0
  320. package/plugins/audit-project/lib/utils/shell-escape.js +88 -0
  321. package/plugins/consult/.claude-plugin/plugin.json +24 -0
  322. package/plugins/consult/agents/consult-agent.md +129 -0
  323. package/plugins/consult/commands/consult.md +248 -0
  324. package/plugins/consult/skills/consult/SKILL.md +285 -0
  325. package/plugins/deslop/.claude-plugin/plugin.json +20 -0
  326. package/plugins/deslop/agents/deslop-agent.md +88 -0
  327. package/plugins/deslop/commands/deslop.md +168 -0
  328. package/plugins/deslop/lib/adapter-transforms.js +278 -0
  329. package/plugins/deslop/lib/collectors/codebase.js +392 -0
  330. package/plugins/deslop/lib/collectors/docs-patterns.js +713 -0
  331. package/plugins/deslop/lib/collectors/documentation.js +219 -0
  332. package/plugins/deslop/lib/collectors/github.js +266 -0
  333. package/plugins/deslop/lib/collectors/index.js +126 -0
  334. package/plugins/deslop/lib/config/index.js +14 -0
  335. package/plugins/deslop/lib/cross-platform/index.js +539 -0
  336. package/plugins/deslop/lib/discovery/index.js +352 -0
  337. package/plugins/deslop/lib/drift-detect/collectors.js +37 -0
  338. package/plugins/deslop/lib/enhance/agent-analyzer.js +421 -0
  339. package/plugins/deslop/lib/enhance/agent-patterns.js +571 -0
  340. package/plugins/deslop/lib/enhance/auto-suppression.js +622 -0
  341. package/plugins/deslop/lib/enhance/benchmark.js +417 -0
  342. package/plugins/deslop/lib/enhance/cross-file-analyzer.js +930 -0
  343. package/plugins/deslop/lib/enhance/cross-file-patterns.js +370 -0
  344. package/plugins/deslop/lib/enhance/docs-analyzer.js +325 -0
  345. package/plugins/deslop/lib/enhance/docs-patterns.js +671 -0
  346. package/plugins/deslop/lib/enhance/fixer.js +721 -0
  347. package/plugins/deslop/lib/enhance/hook-analyzer.js +135 -0
  348. package/plugins/deslop/lib/enhance/hook-patterns.js +40 -0
  349. package/plugins/deslop/lib/enhance/index.js +127 -0
  350. package/plugins/deslop/lib/enhance/plugin-analyzer.js +402 -0
  351. package/plugins/deslop/lib/enhance/plugin-patterns.js +326 -0
  352. package/plugins/deslop/lib/enhance/projectmemory-analyzer.js +551 -0
  353. package/plugins/deslop/lib/enhance/projectmemory-patterns.js +617 -0
  354. package/plugins/deslop/lib/enhance/prompt-analyzer.js +457 -0
  355. package/plugins/deslop/lib/enhance/prompt-patterns.js +1484 -0
  356. package/plugins/deslop/lib/enhance/reporter.js +1348 -0
  357. package/plugins/deslop/lib/enhance/security-patterns.js +284 -0
  358. package/plugins/deslop/lib/enhance/skill-analyzer.js +182 -0
  359. package/plugins/deslop/lib/enhance/skill-patterns.js +147 -0
  360. package/plugins/deslop/lib/enhance/suppression.js +352 -0
  361. package/plugins/deslop/lib/enhance/tool-patterns.js +373 -0
  362. package/plugins/deslop/lib/index.js +270 -0
  363. package/plugins/deslop/lib/patterns/cli-enhancers.js +611 -0
  364. package/plugins/deslop/lib/patterns/pipeline.js +948 -0
  365. package/plugins/deslop/lib/patterns/review-patterns.js +558 -0
  366. package/plugins/deslop/lib/patterns/slop-analyzers.js +2305 -0
  367. package/plugins/deslop/lib/patterns/slop-patterns.js +1187 -0
  368. package/plugins/deslop/lib/perf/analyzer/index.js +22 -0
  369. package/plugins/deslop/lib/perf/argument-parser.js +105 -0
  370. package/plugins/deslop/lib/perf/baseline-comparator.js +50 -0
  371. package/plugins/deslop/lib/perf/baseline-store.js +127 -0
  372. package/plugins/deslop/lib/perf/benchmark-runner.js +399 -0
  373. package/plugins/deslop/lib/perf/breaking-point-finder.js +52 -0
  374. package/plugins/deslop/lib/perf/breaking-point-runner.js +60 -0
  375. package/plugins/deslop/lib/perf/checkpoint.js +123 -0
  376. package/plugins/deslop/lib/perf/code-paths.js +86 -0
  377. package/plugins/deslop/lib/perf/consolidation.js +37 -0
  378. package/plugins/deslop/lib/perf/constraint-runner.js +71 -0
  379. package/plugins/deslop/lib/perf/experiment-runner.js +32 -0
  380. package/plugins/deslop/lib/perf/index.js +41 -0
  381. package/plugins/deslop/lib/perf/investigation-state.js +875 -0
  382. package/plugins/deslop/lib/perf/optimization-runner.js +79 -0
  383. package/plugins/deslop/lib/perf/profilers/go.js +22 -0
  384. package/plugins/deslop/lib/perf/profilers/index.js +46 -0
  385. package/plugins/deslop/lib/perf/profilers/java.js +23 -0
  386. package/plugins/deslop/lib/perf/profilers/node.js +27 -0
  387. package/plugins/deslop/lib/perf/profilers/python.js +23 -0
  388. package/plugins/deslop/lib/perf/profilers/rust.js +23 -0
  389. package/plugins/deslop/lib/perf/profiling-runner.js +56 -0
  390. package/plugins/deslop/lib/perf/schemas.js +140 -0
  391. package/plugins/deslop/lib/platform/detect-platform.js +413 -0
  392. package/plugins/deslop/lib/platform/detection-configs.js +93 -0
  393. package/plugins/deslop/lib/platform/state-dir.js +132 -0
  394. package/plugins/deslop/lib/platform/verify-tools.js +182 -0
  395. package/plugins/deslop/lib/repo-map/cache.js +152 -0
  396. package/plugins/deslop/lib/repo-map/index.js +222 -0
  397. package/plugins/deslop/lib/repo-map/installer.js +212 -0
  398. package/plugins/deslop/lib/repo-map/queries/go.js +27 -0
  399. package/plugins/deslop/lib/repo-map/queries/index.js +100 -0
  400. package/plugins/deslop/lib/repo-map/queries/java.js +38 -0
  401. package/plugins/deslop/lib/repo-map/queries/javascript.js +55 -0
  402. package/plugins/deslop/lib/repo-map/queries/python.js +24 -0
  403. package/plugins/deslop/lib/repo-map/queries/rust.js +73 -0
  404. package/plugins/deslop/lib/repo-map/queries/typescript.js +38 -0
  405. package/plugins/deslop/lib/repo-map/runner.js +1165 -0
  406. package/plugins/deslop/lib/repo-map/updater.js +474 -0
  407. package/plugins/deslop/lib/repo-map/usage-analyzer.js +407 -0
  408. package/plugins/deslop/lib/schemas/plugin-manifest.schema.json +57 -0
  409. package/plugins/deslop/lib/schemas/validator.js +247 -0
  410. package/plugins/deslop/lib/sources/custom-handler.js +199 -0
  411. package/plugins/deslop/lib/sources/policy-questions.js +246 -0
  412. package/plugins/deslop/lib/sources/source-cache.js +165 -0
  413. package/plugins/deslop/lib/state/workflow-state.js +575 -0
  414. package/plugins/deslop/lib/types/agent-frontmatter.d.ts +134 -0
  415. package/plugins/deslop/lib/types/command-frontmatter.d.ts +107 -0
  416. package/plugins/deslop/lib/types/hook-frontmatter.d.ts +115 -0
  417. package/plugins/deslop/lib/types/index.d.ts +84 -0
  418. package/plugins/deslop/lib/types/plugin-manifest.d.ts +102 -0
  419. package/plugins/deslop/lib/types/skill-frontmatter.d.ts +89 -0
  420. package/plugins/deslop/lib/utils/atomic-write.js +94 -0
  421. package/plugins/deslop/lib/utils/cache-manager.js +159 -0
  422. package/plugins/deslop/lib/utils/context-optimizer.js +300 -0
  423. package/plugins/deslop/lib/utils/deprecation.js +37 -0
  424. package/plugins/deslop/lib/utils/shell-escape.js +88 -0
  425. package/plugins/deslop/references/slop-categories.md +122 -0
  426. package/plugins/deslop/scripts/detect.js +134 -0
  427. package/plugins/deslop/skills/deslop/SKILL.md +204 -0
  428. package/plugins/drift-detect/.claude-plugin/plugin.json +23 -0
  429. package/plugins/drift-detect/agents/plan-synthesizer.md +225 -0
  430. package/plugins/drift-detect/commands/drift-detect.md +269 -0
  431. package/plugins/drift-detect/lib/adapter-transforms.js +278 -0
  432. package/plugins/drift-detect/lib/collectors/codebase.js +392 -0
  433. package/plugins/drift-detect/lib/collectors/docs-patterns.js +713 -0
  434. package/plugins/drift-detect/lib/collectors/documentation.js +219 -0
  435. package/plugins/drift-detect/lib/collectors/github.js +266 -0
  436. package/plugins/drift-detect/lib/collectors/index.js +126 -0
  437. package/plugins/drift-detect/lib/config/index.js +14 -0
  438. package/plugins/drift-detect/lib/cross-platform/index.js +539 -0
  439. package/plugins/drift-detect/lib/discovery/index.js +352 -0
  440. package/plugins/drift-detect/lib/drift-detect/collectors.js +37 -0
  441. package/plugins/drift-detect/lib/enhance/agent-analyzer.js +421 -0
  442. package/plugins/drift-detect/lib/enhance/agent-patterns.js +571 -0
  443. package/plugins/drift-detect/lib/enhance/auto-suppression.js +622 -0
  444. package/plugins/drift-detect/lib/enhance/benchmark.js +417 -0
  445. package/plugins/drift-detect/lib/enhance/cross-file-analyzer.js +930 -0
  446. package/plugins/drift-detect/lib/enhance/cross-file-patterns.js +370 -0
  447. package/plugins/drift-detect/lib/enhance/docs-analyzer.js +325 -0
  448. package/plugins/drift-detect/lib/enhance/docs-patterns.js +671 -0
  449. package/plugins/drift-detect/lib/enhance/fixer.js +721 -0
  450. package/plugins/drift-detect/lib/enhance/hook-analyzer.js +135 -0
  451. package/plugins/drift-detect/lib/enhance/hook-patterns.js +40 -0
  452. package/plugins/drift-detect/lib/enhance/index.js +127 -0
  453. package/plugins/drift-detect/lib/enhance/plugin-analyzer.js +402 -0
  454. package/plugins/drift-detect/lib/enhance/plugin-patterns.js +326 -0
  455. package/plugins/drift-detect/lib/enhance/projectmemory-analyzer.js +551 -0
  456. package/plugins/drift-detect/lib/enhance/projectmemory-patterns.js +617 -0
  457. package/plugins/drift-detect/lib/enhance/prompt-analyzer.js +457 -0
  458. package/plugins/drift-detect/lib/enhance/prompt-patterns.js +1484 -0
  459. package/plugins/drift-detect/lib/enhance/reporter.js +1348 -0
  460. package/plugins/drift-detect/lib/enhance/security-patterns.js +284 -0
  461. package/plugins/drift-detect/lib/enhance/skill-analyzer.js +182 -0
  462. package/plugins/drift-detect/lib/enhance/skill-patterns.js +147 -0
  463. package/plugins/drift-detect/lib/enhance/suppression.js +352 -0
  464. package/plugins/drift-detect/lib/enhance/tool-patterns.js +373 -0
  465. package/plugins/drift-detect/lib/index.js +270 -0
  466. package/plugins/drift-detect/lib/patterns/cli-enhancers.js +611 -0
  467. package/plugins/drift-detect/lib/patterns/pipeline.js +948 -0
  468. package/plugins/drift-detect/lib/patterns/review-patterns.js +558 -0
  469. package/plugins/drift-detect/lib/patterns/slop-analyzers.js +2305 -0
  470. package/plugins/drift-detect/lib/patterns/slop-patterns.js +1187 -0
  471. package/plugins/drift-detect/lib/perf/analyzer/index.js +22 -0
  472. package/plugins/drift-detect/lib/perf/argument-parser.js +105 -0
  473. package/plugins/drift-detect/lib/perf/baseline-comparator.js +50 -0
  474. package/plugins/drift-detect/lib/perf/baseline-store.js +127 -0
  475. package/plugins/drift-detect/lib/perf/benchmark-runner.js +399 -0
  476. package/plugins/drift-detect/lib/perf/breaking-point-finder.js +52 -0
  477. package/plugins/drift-detect/lib/perf/breaking-point-runner.js +60 -0
  478. package/plugins/drift-detect/lib/perf/checkpoint.js +123 -0
  479. package/plugins/drift-detect/lib/perf/code-paths.js +86 -0
  480. package/plugins/drift-detect/lib/perf/consolidation.js +37 -0
  481. package/plugins/drift-detect/lib/perf/constraint-runner.js +71 -0
  482. package/plugins/drift-detect/lib/perf/experiment-runner.js +32 -0
  483. package/plugins/drift-detect/lib/perf/index.js +41 -0
  484. package/plugins/drift-detect/lib/perf/investigation-state.js +875 -0
  485. package/plugins/drift-detect/lib/perf/optimization-runner.js +79 -0
  486. package/plugins/drift-detect/lib/perf/profilers/go.js +22 -0
  487. package/plugins/drift-detect/lib/perf/profilers/index.js +46 -0
  488. package/plugins/drift-detect/lib/perf/profilers/java.js +23 -0
  489. package/plugins/drift-detect/lib/perf/profilers/node.js +27 -0
  490. package/plugins/drift-detect/lib/perf/profilers/python.js +23 -0
  491. package/plugins/drift-detect/lib/perf/profilers/rust.js +23 -0
  492. package/plugins/drift-detect/lib/perf/profiling-runner.js +56 -0
  493. package/plugins/drift-detect/lib/perf/schemas.js +140 -0
  494. package/plugins/drift-detect/lib/platform/detect-platform.js +413 -0
  495. package/plugins/drift-detect/lib/platform/detection-configs.js +93 -0
  496. package/plugins/drift-detect/lib/platform/state-dir.js +132 -0
  497. package/plugins/drift-detect/lib/platform/verify-tools.js +182 -0
  498. package/plugins/drift-detect/lib/repo-map/cache.js +152 -0
  499. package/plugins/drift-detect/lib/repo-map/index.js +222 -0
  500. package/plugins/drift-detect/lib/repo-map/installer.js +212 -0
  501. package/plugins/drift-detect/lib/repo-map/queries/go.js +27 -0
  502. package/plugins/drift-detect/lib/repo-map/queries/index.js +100 -0
  503. package/plugins/drift-detect/lib/repo-map/queries/java.js +38 -0
  504. package/plugins/drift-detect/lib/repo-map/queries/javascript.js +55 -0
  505. package/plugins/drift-detect/lib/repo-map/queries/python.js +24 -0
  506. package/plugins/drift-detect/lib/repo-map/queries/rust.js +73 -0
  507. package/plugins/drift-detect/lib/repo-map/queries/typescript.js +38 -0
  508. package/plugins/drift-detect/lib/repo-map/runner.js +1165 -0
  509. package/plugins/drift-detect/lib/repo-map/updater.js +474 -0
  510. package/plugins/drift-detect/lib/repo-map/usage-analyzer.js +407 -0
  511. package/plugins/drift-detect/lib/schemas/plugin-manifest.schema.json +57 -0
  512. package/plugins/drift-detect/lib/schemas/validator.js +247 -0
  513. package/plugins/drift-detect/lib/sources/custom-handler.js +199 -0
  514. package/plugins/drift-detect/lib/sources/policy-questions.js +246 -0
  515. package/plugins/drift-detect/lib/sources/source-cache.js +165 -0
  516. package/plugins/drift-detect/lib/state/workflow-state.js +575 -0
  517. package/plugins/drift-detect/lib/types/agent-frontmatter.d.ts +134 -0
  518. package/plugins/drift-detect/lib/types/command-frontmatter.d.ts +107 -0
  519. package/plugins/drift-detect/lib/types/hook-frontmatter.d.ts +115 -0
  520. package/plugins/drift-detect/lib/types/index.d.ts +84 -0
  521. package/plugins/drift-detect/lib/types/plugin-manifest.d.ts +102 -0
  522. package/plugins/drift-detect/lib/types/skill-frontmatter.d.ts +89 -0
  523. package/plugins/drift-detect/lib/utils/atomic-write.js +94 -0
  524. package/plugins/drift-detect/lib/utils/cache-manager.js +159 -0
  525. package/plugins/drift-detect/lib/utils/context-optimizer.js +300 -0
  526. package/plugins/drift-detect/lib/utils/deprecation.js +37 -0
  527. package/plugins/drift-detect/lib/utils/shell-escape.js +88 -0
  528. package/plugins/drift-detect/skills/drift-analysis/SKILL.md +324 -0
  529. package/plugins/enhance/.claude-plugin/plugin.json +20 -0
  530. package/plugins/enhance/agents/agent-enhancer.md +64 -0
  531. package/plugins/enhance/agents/claudemd-enhancer.md +65 -0
  532. package/plugins/enhance/agents/cross-file-enhancer.md +54 -0
  533. package/plugins/enhance/agents/docs-enhancer.md +64 -0
  534. package/plugins/enhance/agents/hooks-enhancer.md +64 -0
  535. package/plugins/enhance/agents/plugin-enhancer.md +63 -0
  536. package/plugins/enhance/agents/prompt-enhancer.md +58 -0
  537. package/plugins/enhance/agents/skills-enhancer.md +64 -0
  538. package/plugins/enhance/commands/enhance.md +178 -0
  539. package/plugins/enhance/lib/adapter-transforms.js +278 -0
  540. package/plugins/enhance/lib/collectors/codebase.js +392 -0
  541. package/plugins/enhance/lib/collectors/docs-patterns.js +713 -0
  542. package/plugins/enhance/lib/collectors/documentation.js +219 -0
  543. package/plugins/enhance/lib/collectors/github.js +266 -0
  544. package/plugins/enhance/lib/collectors/index.js +126 -0
  545. package/plugins/enhance/lib/config/index.js +14 -0
  546. package/plugins/enhance/lib/cross-platform/index.js +539 -0
  547. package/plugins/enhance/lib/discovery/index.js +352 -0
  548. package/plugins/enhance/lib/drift-detect/collectors.js +37 -0
  549. package/plugins/enhance/lib/enhance/agent-analyzer.js +421 -0
  550. package/plugins/enhance/lib/enhance/agent-patterns.js +571 -0
  551. package/plugins/enhance/lib/enhance/auto-suppression.js +622 -0
  552. package/plugins/enhance/lib/enhance/benchmark.js +417 -0
  553. package/plugins/enhance/lib/enhance/cross-file-analyzer.js +930 -0
  554. package/plugins/enhance/lib/enhance/cross-file-patterns.js +370 -0
  555. package/plugins/enhance/lib/enhance/docs-analyzer.js +325 -0
  556. package/plugins/enhance/lib/enhance/docs-patterns.js +671 -0
  557. package/plugins/enhance/lib/enhance/fixer.js +721 -0
  558. package/plugins/enhance/lib/enhance/hook-analyzer.js +135 -0
  559. package/plugins/enhance/lib/enhance/hook-patterns.js +40 -0
  560. package/plugins/enhance/lib/enhance/index.js +127 -0
  561. package/plugins/enhance/lib/enhance/plugin-analyzer.js +402 -0
  562. package/plugins/enhance/lib/enhance/plugin-patterns.js +326 -0
  563. package/plugins/enhance/lib/enhance/projectmemory-analyzer.js +551 -0
  564. package/plugins/enhance/lib/enhance/projectmemory-patterns.js +617 -0
  565. package/plugins/enhance/lib/enhance/prompt-analyzer.js +457 -0
  566. package/plugins/enhance/lib/enhance/prompt-patterns.js +1484 -0
  567. package/plugins/enhance/lib/enhance/reporter.js +1348 -0
  568. package/plugins/enhance/lib/enhance/security-patterns.js +284 -0
  569. package/plugins/enhance/lib/enhance/skill-analyzer.js +182 -0
  570. package/plugins/enhance/lib/enhance/skill-patterns.js +147 -0
  571. package/plugins/enhance/lib/enhance/suppression.js +352 -0
  572. package/plugins/enhance/lib/enhance/tool-patterns.js +373 -0
  573. package/plugins/enhance/lib/index.js +270 -0
  574. package/plugins/enhance/lib/patterns/cli-enhancers.js +611 -0
  575. package/plugins/enhance/lib/patterns/pipeline.js +948 -0
  576. package/plugins/enhance/lib/patterns/review-patterns.js +558 -0
  577. package/plugins/enhance/lib/patterns/slop-analyzers.js +2305 -0
  578. package/plugins/enhance/lib/patterns/slop-patterns.js +1187 -0
  579. package/plugins/enhance/lib/perf/analyzer/index.js +22 -0
  580. package/plugins/enhance/lib/perf/argument-parser.js +105 -0
  581. package/plugins/enhance/lib/perf/baseline-comparator.js +50 -0
  582. package/plugins/enhance/lib/perf/baseline-store.js +127 -0
  583. package/plugins/enhance/lib/perf/benchmark-runner.js +399 -0
  584. package/plugins/enhance/lib/perf/breaking-point-finder.js +52 -0
  585. package/plugins/enhance/lib/perf/breaking-point-runner.js +60 -0
  586. package/plugins/enhance/lib/perf/checkpoint.js +123 -0
  587. package/plugins/enhance/lib/perf/code-paths.js +86 -0
  588. package/plugins/enhance/lib/perf/consolidation.js +37 -0
  589. package/plugins/enhance/lib/perf/constraint-runner.js +71 -0
  590. package/plugins/enhance/lib/perf/experiment-runner.js +32 -0
  591. package/plugins/enhance/lib/perf/index.js +41 -0
  592. package/plugins/enhance/lib/perf/investigation-state.js +875 -0
  593. package/plugins/enhance/lib/perf/optimization-runner.js +79 -0
  594. package/plugins/enhance/lib/perf/profilers/go.js +22 -0
  595. package/plugins/enhance/lib/perf/profilers/index.js +46 -0
  596. package/plugins/enhance/lib/perf/profilers/java.js +23 -0
  597. package/plugins/enhance/lib/perf/profilers/node.js +27 -0
  598. package/plugins/enhance/lib/perf/profilers/python.js +23 -0
  599. package/plugins/enhance/lib/perf/profilers/rust.js +23 -0
  600. package/plugins/enhance/lib/perf/profiling-runner.js +56 -0
  601. package/plugins/enhance/lib/perf/schemas.js +140 -0
  602. package/plugins/enhance/lib/platform/detect-platform.js +413 -0
  603. package/plugins/enhance/lib/platform/detection-configs.js +93 -0
  604. package/plugins/enhance/lib/platform/state-dir.js +132 -0
  605. package/plugins/enhance/lib/platform/verify-tools.js +182 -0
  606. package/plugins/enhance/lib/repo-map/cache.js +152 -0
  607. package/plugins/enhance/lib/repo-map/index.js +222 -0
  608. package/plugins/enhance/lib/repo-map/installer.js +212 -0
  609. package/plugins/enhance/lib/repo-map/queries/go.js +27 -0
  610. package/plugins/enhance/lib/repo-map/queries/index.js +100 -0
  611. package/plugins/enhance/lib/repo-map/queries/java.js +38 -0
  612. package/plugins/enhance/lib/repo-map/queries/javascript.js +55 -0
  613. package/plugins/enhance/lib/repo-map/queries/python.js +24 -0
  614. package/plugins/enhance/lib/repo-map/queries/rust.js +73 -0
  615. package/plugins/enhance/lib/repo-map/queries/typescript.js +38 -0
  616. package/plugins/enhance/lib/repo-map/runner.js +1165 -0
  617. package/plugins/enhance/lib/repo-map/updater.js +474 -0
  618. package/plugins/enhance/lib/repo-map/usage-analyzer.js +407 -0
  619. package/plugins/enhance/lib/schemas/plugin-manifest.schema.json +57 -0
  620. package/plugins/enhance/lib/schemas/validator.js +247 -0
  621. package/plugins/enhance/lib/sources/custom-handler.js +199 -0
  622. package/plugins/enhance/lib/sources/policy-questions.js +246 -0
  623. package/plugins/enhance/lib/sources/source-cache.js +165 -0
  624. package/plugins/enhance/lib/state/workflow-state.js +575 -0
  625. package/plugins/enhance/lib/types/agent-frontmatter.d.ts +134 -0
  626. package/plugins/enhance/lib/types/command-frontmatter.d.ts +107 -0
  627. package/plugins/enhance/lib/types/hook-frontmatter.d.ts +115 -0
  628. package/plugins/enhance/lib/types/index.d.ts +84 -0
  629. package/plugins/enhance/lib/types/plugin-manifest.d.ts +102 -0
  630. package/plugins/enhance/lib/types/skill-frontmatter.d.ts +89 -0
  631. package/plugins/enhance/lib/utils/atomic-write.js +94 -0
  632. package/plugins/enhance/lib/utils/cache-manager.js +159 -0
  633. package/plugins/enhance/lib/utils/context-optimizer.js +300 -0
  634. package/plugins/enhance/lib/utils/deprecation.js +37 -0
  635. package/plugins/enhance/lib/utils/shell-escape.js +88 -0
  636. package/plugins/enhance/skills/enhance-agent-prompts/SKILL.md +277 -0
  637. package/plugins/enhance/skills/enhance-claude-memory/SKILL.md +387 -0
  638. package/plugins/enhance/skills/enhance-cross-file/SKILL.md +110 -0
  639. package/plugins/enhance/skills/enhance-docs/SKILL.md +298 -0
  640. package/plugins/enhance/skills/enhance-hooks/SKILL.md +554 -0
  641. package/plugins/enhance/skills/enhance-orchestrator/SKILL.md +255 -0
  642. package/plugins/enhance/skills/enhance-plugins/SKILL.md +319 -0
  643. package/plugins/enhance/skills/enhance-prompts/SKILL.md +340 -0
  644. package/plugins/enhance/skills/enhance-skills/SKILL.md +436 -0
  645. package/plugins/learn/.claude-plugin/plugin.json +21 -0
  646. package/plugins/learn/agents/learn-agent.md +331 -0
  647. package/plugins/learn/commands/learn.md +190 -0
  648. package/plugins/learn/lib/adapter-transforms.js +278 -0
  649. package/plugins/learn/lib/collectors/codebase.js +392 -0
  650. package/plugins/learn/lib/collectors/docs-patterns.js +713 -0
  651. package/plugins/learn/lib/collectors/documentation.js +219 -0
  652. package/plugins/learn/lib/collectors/github.js +266 -0
  653. package/plugins/learn/lib/collectors/index.js +126 -0
  654. package/plugins/learn/lib/config/index.js +14 -0
  655. package/plugins/learn/lib/cross-platform/index.js +539 -0
  656. package/plugins/learn/lib/discovery/index.js +352 -0
  657. package/plugins/learn/lib/drift-detect/collectors.js +37 -0
  658. package/plugins/learn/lib/enhance/agent-analyzer.js +421 -0
  659. package/plugins/learn/lib/enhance/agent-patterns.js +571 -0
  660. package/plugins/learn/lib/enhance/auto-suppression.js +622 -0
  661. package/plugins/learn/lib/enhance/benchmark.js +417 -0
  662. package/plugins/learn/lib/enhance/cross-file-analyzer.js +930 -0
  663. package/plugins/learn/lib/enhance/cross-file-patterns.js +370 -0
  664. package/plugins/learn/lib/enhance/docs-analyzer.js +325 -0
  665. package/plugins/learn/lib/enhance/docs-patterns.js +671 -0
  666. package/plugins/learn/lib/enhance/fixer.js +721 -0
  667. package/plugins/learn/lib/enhance/hook-analyzer.js +135 -0
  668. package/plugins/learn/lib/enhance/hook-patterns.js +40 -0
  669. package/plugins/learn/lib/enhance/index.js +127 -0
  670. package/plugins/learn/lib/enhance/plugin-analyzer.js +402 -0
  671. package/plugins/learn/lib/enhance/plugin-patterns.js +326 -0
  672. package/plugins/learn/lib/enhance/projectmemory-analyzer.js +551 -0
  673. package/plugins/learn/lib/enhance/projectmemory-patterns.js +617 -0
  674. package/plugins/learn/lib/enhance/prompt-analyzer.js +457 -0
  675. package/plugins/learn/lib/enhance/prompt-patterns.js +1484 -0
  676. package/plugins/learn/lib/enhance/reporter.js +1348 -0
  677. package/plugins/learn/lib/enhance/security-patterns.js +284 -0
  678. package/plugins/learn/lib/enhance/skill-analyzer.js +182 -0
  679. package/plugins/learn/lib/enhance/skill-patterns.js +147 -0
  680. package/plugins/learn/lib/enhance/suppression.js +352 -0
  681. package/plugins/learn/lib/enhance/tool-patterns.js +373 -0
  682. package/plugins/learn/lib/index.js +270 -0
  683. package/plugins/learn/lib/patterns/cli-enhancers.js +611 -0
  684. package/plugins/learn/lib/patterns/pipeline.js +948 -0
  685. package/plugins/learn/lib/patterns/review-patterns.js +558 -0
  686. package/plugins/learn/lib/patterns/slop-analyzers.js +2305 -0
  687. package/plugins/learn/lib/patterns/slop-patterns.js +1187 -0
  688. package/plugins/learn/lib/perf/analyzer/index.js +22 -0
  689. package/plugins/learn/lib/perf/argument-parser.js +105 -0
  690. package/plugins/learn/lib/perf/baseline-comparator.js +50 -0
  691. package/plugins/learn/lib/perf/baseline-store.js +127 -0
  692. package/plugins/learn/lib/perf/benchmark-runner.js +399 -0
  693. package/plugins/learn/lib/perf/breaking-point-finder.js +52 -0
  694. package/plugins/learn/lib/perf/breaking-point-runner.js +60 -0
  695. package/plugins/learn/lib/perf/checkpoint.js +123 -0
  696. package/plugins/learn/lib/perf/code-paths.js +86 -0
  697. package/plugins/learn/lib/perf/consolidation.js +37 -0
  698. package/plugins/learn/lib/perf/constraint-runner.js +71 -0
  699. package/plugins/learn/lib/perf/experiment-runner.js +32 -0
  700. package/plugins/learn/lib/perf/index.js +41 -0
  701. package/plugins/learn/lib/perf/investigation-state.js +875 -0
  702. package/plugins/learn/lib/perf/optimization-runner.js +79 -0
  703. package/plugins/learn/lib/perf/profilers/go.js +22 -0
  704. package/plugins/learn/lib/perf/profilers/index.js +46 -0
  705. package/plugins/learn/lib/perf/profilers/java.js +23 -0
  706. package/plugins/learn/lib/perf/profilers/node.js +27 -0
  707. package/plugins/learn/lib/perf/profilers/python.js +23 -0
  708. package/plugins/learn/lib/perf/profilers/rust.js +23 -0
  709. package/plugins/learn/lib/perf/profiling-runner.js +56 -0
  710. package/plugins/learn/lib/perf/schemas.js +140 -0
  711. package/plugins/learn/lib/platform/detect-platform.js +413 -0
  712. package/plugins/learn/lib/platform/detection-configs.js +93 -0
  713. package/plugins/learn/lib/platform/state-dir.js +132 -0
  714. package/plugins/learn/lib/platform/verify-tools.js +182 -0
  715. package/plugins/learn/lib/repo-map/cache.js +152 -0
  716. package/plugins/learn/lib/repo-map/index.js +222 -0
  717. package/plugins/learn/lib/repo-map/installer.js +212 -0
  718. package/plugins/learn/lib/repo-map/queries/go.js +27 -0
  719. package/plugins/learn/lib/repo-map/queries/index.js +100 -0
  720. package/plugins/learn/lib/repo-map/queries/java.js +38 -0
  721. package/plugins/learn/lib/repo-map/queries/javascript.js +55 -0
  722. package/plugins/learn/lib/repo-map/queries/python.js +24 -0
  723. package/plugins/learn/lib/repo-map/queries/rust.js +73 -0
  724. package/plugins/learn/lib/repo-map/queries/typescript.js +38 -0
  725. package/plugins/learn/lib/repo-map/runner.js +1165 -0
  726. package/plugins/learn/lib/repo-map/updater.js +474 -0
  727. package/plugins/learn/lib/repo-map/usage-analyzer.js +407 -0
  728. package/plugins/learn/lib/schemas/plugin-manifest.schema.json +57 -0
  729. package/plugins/learn/lib/schemas/validator.js +247 -0
  730. package/plugins/learn/lib/sources/custom-handler.js +199 -0
  731. package/plugins/learn/lib/sources/policy-questions.js +246 -0
  732. package/plugins/learn/lib/sources/source-cache.js +165 -0
  733. package/plugins/learn/lib/state/workflow-state.js +575 -0
  734. package/plugins/learn/lib/types/agent-frontmatter.d.ts +134 -0
  735. package/plugins/learn/lib/types/command-frontmatter.d.ts +107 -0
  736. package/plugins/learn/lib/types/hook-frontmatter.d.ts +115 -0
  737. package/plugins/learn/lib/types/index.d.ts +84 -0
  738. package/plugins/learn/lib/types/plugin-manifest.d.ts +102 -0
  739. package/plugins/learn/lib/types/skill-frontmatter.d.ts +89 -0
  740. package/plugins/learn/lib/utils/atomic-write.js +94 -0
  741. package/plugins/learn/lib/utils/cache-manager.js +159 -0
  742. package/plugins/learn/lib/utils/context-optimizer.js +300 -0
  743. package/plugins/learn/lib/utils/deprecation.js +37 -0
  744. package/plugins/learn/lib/utils/shell-escape.js +88 -0
  745. package/plugins/learn/skills/learn/SKILL.md +349 -0
  746. package/plugins/next-task/.claude-plugin/plugin.json +24 -0
  747. package/plugins/next-task/agents/ci-fixer.md +259 -0
  748. package/plugins/next-task/agents/ci-monitor.md +342 -0
  749. package/plugins/next-task/agents/delivery-validator.md +115 -0
  750. package/plugins/next-task/agents/exploration-agent.md +316 -0
  751. package/plugins/next-task/agents/implementation-agent.md +465 -0
  752. package/plugins/next-task/agents/planning-agent.md +377 -0
  753. package/plugins/next-task/agents/simple-fixer.md +139 -0
  754. package/plugins/next-task/agents/task-discoverer.md +89 -0
  755. package/plugins/next-task/agents/test-coverage-checker.md +451 -0
  756. package/plugins/next-task/agents/worktree-manager.md +257 -0
  757. package/plugins/next-task/commands/delivery-approval.md +341 -0
  758. package/plugins/next-task/commands/next-task.md +547 -0
  759. package/plugins/next-task/hooks/hooks.json +14 -0
  760. package/plugins/next-task/lib/adapter-transforms.js +278 -0
  761. package/plugins/next-task/lib/collectors/codebase.js +392 -0
  762. package/plugins/next-task/lib/collectors/docs-patterns.js +713 -0
  763. package/plugins/next-task/lib/collectors/documentation.js +219 -0
  764. package/plugins/next-task/lib/collectors/github.js +266 -0
  765. package/plugins/next-task/lib/collectors/index.js +126 -0
  766. package/plugins/next-task/lib/config/index.js +14 -0
  767. package/plugins/next-task/lib/cross-platform/index.js +539 -0
  768. package/plugins/next-task/lib/discovery/index.js +352 -0
  769. package/plugins/next-task/lib/drift-detect/collectors.js +37 -0
  770. package/plugins/next-task/lib/enhance/agent-analyzer.js +421 -0
  771. package/plugins/next-task/lib/enhance/agent-patterns.js +571 -0
  772. package/plugins/next-task/lib/enhance/auto-suppression.js +622 -0
  773. package/plugins/next-task/lib/enhance/benchmark.js +417 -0
  774. package/plugins/next-task/lib/enhance/cross-file-analyzer.js +930 -0
  775. package/plugins/next-task/lib/enhance/cross-file-patterns.js +370 -0
  776. package/plugins/next-task/lib/enhance/docs-analyzer.js +325 -0
  777. package/plugins/next-task/lib/enhance/docs-patterns.js +671 -0
  778. package/plugins/next-task/lib/enhance/fixer.js +721 -0
  779. package/plugins/next-task/lib/enhance/hook-analyzer.js +135 -0
  780. package/plugins/next-task/lib/enhance/hook-patterns.js +40 -0
  781. package/plugins/next-task/lib/enhance/index.js +127 -0
  782. package/plugins/next-task/lib/enhance/plugin-analyzer.js +402 -0
  783. package/plugins/next-task/lib/enhance/plugin-patterns.js +326 -0
  784. package/plugins/next-task/lib/enhance/projectmemory-analyzer.js +551 -0
  785. package/plugins/next-task/lib/enhance/projectmemory-patterns.js +617 -0
  786. package/plugins/next-task/lib/enhance/prompt-analyzer.js +457 -0
  787. package/plugins/next-task/lib/enhance/prompt-patterns.js +1484 -0
  788. package/plugins/next-task/lib/enhance/reporter.js +1348 -0
  789. package/plugins/next-task/lib/enhance/security-patterns.js +284 -0
  790. package/plugins/next-task/lib/enhance/skill-analyzer.js +182 -0
  791. package/plugins/next-task/lib/enhance/skill-patterns.js +147 -0
  792. package/plugins/next-task/lib/enhance/suppression.js +352 -0
  793. package/plugins/next-task/lib/enhance/tool-patterns.js +373 -0
  794. package/plugins/next-task/lib/index.js +270 -0
  795. package/plugins/next-task/lib/patterns/cli-enhancers.js +611 -0
  796. package/plugins/next-task/lib/patterns/pipeline.js +948 -0
  797. package/plugins/next-task/lib/patterns/review-patterns.js +558 -0
  798. package/plugins/next-task/lib/patterns/slop-analyzers.js +2305 -0
  799. package/plugins/next-task/lib/patterns/slop-patterns.js +1187 -0
  800. package/plugins/next-task/lib/perf/analyzer/index.js +22 -0
  801. package/plugins/next-task/lib/perf/argument-parser.js +105 -0
  802. package/plugins/next-task/lib/perf/baseline-comparator.js +50 -0
  803. package/plugins/next-task/lib/perf/baseline-store.js +127 -0
  804. package/plugins/next-task/lib/perf/benchmark-runner.js +399 -0
  805. package/plugins/next-task/lib/perf/breaking-point-finder.js +52 -0
  806. package/plugins/next-task/lib/perf/breaking-point-runner.js +60 -0
  807. package/plugins/next-task/lib/perf/checkpoint.js +123 -0
  808. package/plugins/next-task/lib/perf/code-paths.js +86 -0
  809. package/plugins/next-task/lib/perf/consolidation.js +37 -0
  810. package/plugins/next-task/lib/perf/constraint-runner.js +71 -0
  811. package/plugins/next-task/lib/perf/experiment-runner.js +32 -0
  812. package/plugins/next-task/lib/perf/index.js +41 -0
  813. package/plugins/next-task/lib/perf/investigation-state.js +875 -0
  814. package/plugins/next-task/lib/perf/optimization-runner.js +79 -0
  815. package/plugins/next-task/lib/perf/profilers/go.js +22 -0
  816. package/plugins/next-task/lib/perf/profilers/index.js +46 -0
  817. package/plugins/next-task/lib/perf/profilers/java.js +23 -0
  818. package/plugins/next-task/lib/perf/profilers/node.js +27 -0
  819. package/plugins/next-task/lib/perf/profilers/python.js +23 -0
  820. package/plugins/next-task/lib/perf/profilers/rust.js +23 -0
  821. package/plugins/next-task/lib/perf/profiling-runner.js +56 -0
  822. package/plugins/next-task/lib/perf/schemas.js +140 -0
  823. package/plugins/next-task/lib/platform/detect-platform.js +413 -0
  824. package/plugins/next-task/lib/platform/detection-configs.js +93 -0
  825. package/plugins/next-task/lib/platform/state-dir.js +132 -0
  826. package/plugins/next-task/lib/platform/verify-tools.js +182 -0
  827. package/plugins/next-task/lib/repo-map/cache.js +152 -0
  828. package/plugins/next-task/lib/repo-map/index.js +222 -0
  829. package/plugins/next-task/lib/repo-map/installer.js +212 -0
  830. package/plugins/next-task/lib/repo-map/queries/go.js +27 -0
  831. package/plugins/next-task/lib/repo-map/queries/index.js +100 -0
  832. package/plugins/next-task/lib/repo-map/queries/java.js +38 -0
  833. package/plugins/next-task/lib/repo-map/queries/javascript.js +55 -0
  834. package/plugins/next-task/lib/repo-map/queries/python.js +24 -0
  835. package/plugins/next-task/lib/repo-map/queries/rust.js +73 -0
  836. package/plugins/next-task/lib/repo-map/queries/typescript.js +38 -0
  837. package/plugins/next-task/lib/repo-map/runner.js +1165 -0
  838. package/plugins/next-task/lib/repo-map/updater.js +474 -0
  839. package/plugins/next-task/lib/repo-map/usage-analyzer.js +407 -0
  840. package/plugins/next-task/lib/schemas/plugin-manifest.schema.json +57 -0
  841. package/plugins/next-task/lib/schemas/validator.js +247 -0
  842. package/plugins/next-task/lib/sources/custom-handler.js +199 -0
  843. package/plugins/next-task/lib/sources/policy-questions.js +246 -0
  844. package/plugins/next-task/lib/sources/source-cache.js +165 -0
  845. package/plugins/next-task/lib/state/workflow-state.js +575 -0
  846. package/plugins/next-task/lib/types/agent-frontmatter.d.ts +134 -0
  847. package/plugins/next-task/lib/types/command-frontmatter.d.ts +107 -0
  848. package/plugins/next-task/lib/types/hook-frontmatter.d.ts +115 -0
  849. package/plugins/next-task/lib/types/index.d.ts +84 -0
  850. package/plugins/next-task/lib/types/plugin-manifest.d.ts +102 -0
  851. package/plugins/next-task/lib/types/skill-frontmatter.d.ts +89 -0
  852. package/plugins/next-task/lib/utils/atomic-write.js +94 -0
  853. package/plugins/next-task/lib/utils/cache-manager.js +159 -0
  854. package/plugins/next-task/lib/utils/context-optimizer.js +300 -0
  855. package/plugins/next-task/lib/utils/deprecation.js +37 -0
  856. package/plugins/next-task/lib/utils/shell-escape.js +88 -0
  857. package/plugins/next-task/skills/discover-tasks/SKILL.md +191 -0
  858. package/plugins/next-task/skills/orchestrate-review/SKILL.md +239 -0
  859. package/plugins/next-task/skills/validate-delivery/SKILL.md +186 -0
  860. package/plugins/perf/.claude-plugin/plugin.json +20 -0
  861. package/plugins/perf/agents/perf-analyzer.md +43 -0
  862. package/plugins/perf/agents/perf-code-paths.md +16 -0
  863. package/plugins/perf/agents/perf-investigation-logger.md +47 -0
  864. package/plugins/perf/agents/perf-orchestrator.md +344 -0
  865. package/plugins/perf/agents/perf-theory-gatherer.md +25 -0
  866. package/plugins/perf/agents/perf-theory-tester.md +58 -0
  867. package/plugins/perf/commands/perf.md +470 -0
  868. package/plugins/perf/hooks/checkpoint.md +35 -0
  869. package/plugins/perf/hooks/constraint-tester.md +40 -0
  870. package/plugins/perf/lib/adapter-transforms.js +278 -0
  871. package/plugins/perf/lib/collectors/codebase.js +392 -0
  872. package/plugins/perf/lib/collectors/docs-patterns.js +713 -0
  873. package/plugins/perf/lib/collectors/documentation.js +219 -0
  874. package/plugins/perf/lib/collectors/github.js +266 -0
  875. package/plugins/perf/lib/collectors/index.js +126 -0
  876. package/plugins/perf/lib/config/index.js +14 -0
  877. package/plugins/perf/lib/cross-platform/index.js +539 -0
  878. package/plugins/perf/lib/discovery/index.js +352 -0
  879. package/plugins/perf/lib/drift-detect/collectors.js +37 -0
  880. package/plugins/perf/lib/enhance/agent-analyzer.js +421 -0
  881. package/plugins/perf/lib/enhance/agent-patterns.js +571 -0
  882. package/plugins/perf/lib/enhance/auto-suppression.js +622 -0
  883. package/plugins/perf/lib/enhance/benchmark.js +417 -0
  884. package/plugins/perf/lib/enhance/cross-file-analyzer.js +930 -0
  885. package/plugins/perf/lib/enhance/cross-file-patterns.js +370 -0
  886. package/plugins/perf/lib/enhance/docs-analyzer.js +325 -0
  887. package/plugins/perf/lib/enhance/docs-patterns.js +671 -0
  888. package/plugins/perf/lib/enhance/fixer.js +721 -0
  889. package/plugins/perf/lib/enhance/hook-analyzer.js +135 -0
  890. package/plugins/perf/lib/enhance/hook-patterns.js +40 -0
  891. package/plugins/perf/lib/enhance/index.js +127 -0
  892. package/plugins/perf/lib/enhance/plugin-analyzer.js +402 -0
  893. package/plugins/perf/lib/enhance/plugin-patterns.js +326 -0
  894. package/plugins/perf/lib/enhance/projectmemory-analyzer.js +551 -0
  895. package/plugins/perf/lib/enhance/projectmemory-patterns.js +617 -0
  896. package/plugins/perf/lib/enhance/prompt-analyzer.js +457 -0
  897. package/plugins/perf/lib/enhance/prompt-patterns.js +1484 -0
  898. package/plugins/perf/lib/enhance/reporter.js +1348 -0
  899. package/plugins/perf/lib/enhance/security-patterns.js +284 -0
  900. package/plugins/perf/lib/enhance/skill-analyzer.js +182 -0
  901. package/plugins/perf/lib/enhance/skill-patterns.js +147 -0
  902. package/plugins/perf/lib/enhance/suppression.js +352 -0
  903. package/plugins/perf/lib/enhance/tool-patterns.js +373 -0
  904. package/plugins/perf/lib/index.js +270 -0
  905. package/plugins/perf/lib/patterns/cli-enhancers.js +611 -0
  906. package/plugins/perf/lib/patterns/pipeline.js +948 -0
  907. package/plugins/perf/lib/patterns/review-patterns.js +558 -0
  908. package/plugins/perf/lib/patterns/slop-analyzers.js +2305 -0
  909. package/plugins/perf/lib/patterns/slop-patterns.js +1187 -0
  910. package/plugins/perf/lib/perf/analyzer/index.js +22 -0
  911. package/plugins/perf/lib/perf/argument-parser.js +105 -0
  912. package/plugins/perf/lib/perf/baseline-comparator.js +50 -0
  913. package/plugins/perf/lib/perf/baseline-store.js +127 -0
  914. package/plugins/perf/lib/perf/benchmark-runner.js +399 -0
  915. package/plugins/perf/lib/perf/breaking-point-finder.js +52 -0
  916. package/plugins/perf/lib/perf/breaking-point-runner.js +60 -0
  917. package/plugins/perf/lib/perf/checkpoint.js +123 -0
  918. package/plugins/perf/lib/perf/code-paths.js +86 -0
  919. package/plugins/perf/lib/perf/consolidation.js +37 -0
  920. package/plugins/perf/lib/perf/constraint-runner.js +71 -0
  921. package/plugins/perf/lib/perf/experiment-runner.js +32 -0
  922. package/plugins/perf/lib/perf/index.js +41 -0
  923. package/plugins/perf/lib/perf/investigation-state.js +875 -0
  924. package/plugins/perf/lib/perf/optimization-runner.js +79 -0
  925. package/plugins/perf/lib/perf/profilers/go.js +22 -0
  926. package/plugins/perf/lib/perf/profilers/index.js +46 -0
  927. package/plugins/perf/lib/perf/profilers/java.js +23 -0
  928. package/plugins/perf/lib/perf/profilers/node.js +27 -0
  929. package/plugins/perf/lib/perf/profilers/python.js +23 -0
  930. package/plugins/perf/lib/perf/profilers/rust.js +23 -0
  931. package/plugins/perf/lib/perf/profiling-runner.js +56 -0
  932. package/plugins/perf/lib/perf/schemas.js +140 -0
  933. package/plugins/perf/lib/platform/detect-platform.js +413 -0
  934. package/plugins/perf/lib/platform/detection-configs.js +93 -0
  935. package/plugins/perf/lib/platform/state-dir.js +132 -0
  936. package/plugins/perf/lib/platform/verify-tools.js +182 -0
  937. package/plugins/perf/lib/repo-map/cache.js +152 -0
  938. package/plugins/perf/lib/repo-map/index.js +222 -0
  939. package/plugins/perf/lib/repo-map/installer.js +212 -0
  940. package/plugins/perf/lib/repo-map/queries/go.js +27 -0
  941. package/plugins/perf/lib/repo-map/queries/index.js +100 -0
  942. package/plugins/perf/lib/repo-map/queries/java.js +38 -0
  943. package/plugins/perf/lib/repo-map/queries/javascript.js +55 -0
  944. package/plugins/perf/lib/repo-map/queries/python.js +24 -0
  945. package/plugins/perf/lib/repo-map/queries/rust.js +73 -0
  946. package/plugins/perf/lib/repo-map/queries/typescript.js +38 -0
  947. package/plugins/perf/lib/repo-map/runner.js +1165 -0
  948. package/plugins/perf/lib/repo-map/updater.js +474 -0
  949. package/plugins/perf/lib/repo-map/usage-analyzer.js +407 -0
  950. package/plugins/perf/lib/schemas/plugin-manifest.schema.json +57 -0
  951. package/plugins/perf/lib/schemas/validator.js +247 -0
  952. package/plugins/perf/lib/sources/custom-handler.js +199 -0
  953. package/plugins/perf/lib/sources/policy-questions.js +246 -0
  954. package/plugins/perf/lib/sources/source-cache.js +165 -0
  955. package/plugins/perf/lib/state/workflow-state.js +575 -0
  956. package/plugins/perf/lib/types/agent-frontmatter.d.ts +134 -0
  957. package/plugins/perf/lib/types/command-frontmatter.d.ts +107 -0
  958. package/plugins/perf/lib/types/hook-frontmatter.d.ts +115 -0
  959. package/plugins/perf/lib/types/index.d.ts +84 -0
  960. package/plugins/perf/lib/types/plugin-manifest.d.ts +102 -0
  961. package/plugins/perf/lib/types/skill-frontmatter.d.ts +89 -0
  962. package/plugins/perf/lib/utils/atomic-write.js +94 -0
  963. package/plugins/perf/lib/utils/cache-manager.js +159 -0
  964. package/plugins/perf/lib/utils/context-optimizer.js +300 -0
  965. package/plugins/perf/lib/utils/deprecation.js +37 -0
  966. package/plugins/perf/lib/utils/shell-escape.js +88 -0
  967. package/plugins/perf/skills/perf-analyzer/SKILL.md +37 -0
  968. package/plugins/perf/skills/perf-baseline-manager/SKILL.md +30 -0
  969. package/plugins/perf/skills/perf-benchmarker/SKILL.md +52 -0
  970. package/plugins/perf/skills/perf-code-paths/SKILL.md +32 -0
  971. package/plugins/perf/skills/perf-investigation-logger/SKILL.md +41 -0
  972. package/plugins/perf/skills/perf-profiler/SKILL.md +42 -0
  973. package/plugins/perf/skills/perf-theory-gatherer/SKILL.md +35 -0
  974. package/plugins/perf/skills/perf-theory-tester/SKILL.md +36 -0
  975. package/plugins/repo-map/.claude-plugin/plugin.json +22 -0
  976. package/plugins/repo-map/agents/map-validator.md +60 -0
  977. package/plugins/repo-map/commands/repo-map.md +133 -0
  978. package/plugins/repo-map/lib/adapter-transforms.js +278 -0
  979. package/plugins/repo-map/lib/collectors/codebase.js +392 -0
  980. package/plugins/repo-map/lib/collectors/docs-patterns.js +713 -0
  981. package/plugins/repo-map/lib/collectors/documentation.js +219 -0
  982. package/plugins/repo-map/lib/collectors/github.js +266 -0
  983. package/plugins/repo-map/lib/collectors/index.js +126 -0
  984. package/plugins/repo-map/lib/config/index.js +14 -0
  985. package/plugins/repo-map/lib/cross-platform/index.js +539 -0
  986. package/plugins/repo-map/lib/discovery/index.js +352 -0
  987. package/plugins/repo-map/lib/drift-detect/collectors.js +37 -0
  988. package/plugins/repo-map/lib/enhance/agent-analyzer.js +421 -0
  989. package/plugins/repo-map/lib/enhance/agent-patterns.js +571 -0
  990. package/plugins/repo-map/lib/enhance/auto-suppression.js +622 -0
  991. package/plugins/repo-map/lib/enhance/benchmark.js +417 -0
  992. package/plugins/repo-map/lib/enhance/cross-file-analyzer.js +930 -0
  993. package/plugins/repo-map/lib/enhance/cross-file-patterns.js +370 -0
  994. package/plugins/repo-map/lib/enhance/docs-analyzer.js +325 -0
  995. package/plugins/repo-map/lib/enhance/docs-patterns.js +671 -0
  996. package/plugins/repo-map/lib/enhance/fixer.js +721 -0
  997. package/plugins/repo-map/lib/enhance/hook-analyzer.js +135 -0
  998. package/plugins/repo-map/lib/enhance/hook-patterns.js +40 -0
  999. package/plugins/repo-map/lib/enhance/index.js +127 -0
  1000. package/plugins/repo-map/lib/enhance/plugin-analyzer.js +402 -0
  1001. package/plugins/repo-map/lib/enhance/plugin-patterns.js +326 -0
  1002. package/plugins/repo-map/lib/enhance/projectmemory-analyzer.js +551 -0
  1003. package/plugins/repo-map/lib/enhance/projectmemory-patterns.js +617 -0
  1004. package/plugins/repo-map/lib/enhance/prompt-analyzer.js +457 -0
  1005. package/plugins/repo-map/lib/enhance/prompt-patterns.js +1484 -0
  1006. package/plugins/repo-map/lib/enhance/reporter.js +1348 -0
  1007. package/plugins/repo-map/lib/enhance/security-patterns.js +284 -0
  1008. package/plugins/repo-map/lib/enhance/skill-analyzer.js +182 -0
  1009. package/plugins/repo-map/lib/enhance/skill-patterns.js +147 -0
  1010. package/plugins/repo-map/lib/enhance/suppression.js +352 -0
  1011. package/plugins/repo-map/lib/enhance/tool-patterns.js +373 -0
  1012. package/plugins/repo-map/lib/index.js +270 -0
  1013. package/plugins/repo-map/lib/patterns/cli-enhancers.js +611 -0
  1014. package/plugins/repo-map/lib/patterns/pipeline.js +948 -0
  1015. package/plugins/repo-map/lib/patterns/review-patterns.js +558 -0
  1016. package/plugins/repo-map/lib/patterns/slop-analyzers.js +2305 -0
  1017. package/plugins/repo-map/lib/patterns/slop-patterns.js +1187 -0
  1018. package/plugins/repo-map/lib/perf/analyzer/index.js +22 -0
  1019. package/plugins/repo-map/lib/perf/argument-parser.js +105 -0
  1020. package/plugins/repo-map/lib/perf/baseline-comparator.js +50 -0
  1021. package/plugins/repo-map/lib/perf/baseline-store.js +127 -0
  1022. package/plugins/repo-map/lib/perf/benchmark-runner.js +399 -0
  1023. package/plugins/repo-map/lib/perf/breaking-point-finder.js +52 -0
  1024. package/plugins/repo-map/lib/perf/breaking-point-runner.js +60 -0
  1025. package/plugins/repo-map/lib/perf/checkpoint.js +123 -0
  1026. package/plugins/repo-map/lib/perf/code-paths.js +86 -0
  1027. package/plugins/repo-map/lib/perf/consolidation.js +37 -0
  1028. package/plugins/repo-map/lib/perf/constraint-runner.js +71 -0
  1029. package/plugins/repo-map/lib/perf/experiment-runner.js +32 -0
  1030. package/plugins/repo-map/lib/perf/index.js +41 -0
  1031. package/plugins/repo-map/lib/perf/investigation-state.js +875 -0
  1032. package/plugins/repo-map/lib/perf/optimization-runner.js +79 -0
  1033. package/plugins/repo-map/lib/perf/profilers/go.js +22 -0
  1034. package/plugins/repo-map/lib/perf/profilers/index.js +46 -0
  1035. package/plugins/repo-map/lib/perf/profilers/java.js +23 -0
  1036. package/plugins/repo-map/lib/perf/profilers/node.js +27 -0
  1037. package/plugins/repo-map/lib/perf/profilers/python.js +23 -0
  1038. package/plugins/repo-map/lib/perf/profilers/rust.js +23 -0
  1039. package/plugins/repo-map/lib/perf/profiling-runner.js +56 -0
  1040. package/plugins/repo-map/lib/perf/schemas.js +140 -0
  1041. package/plugins/repo-map/lib/platform/detect-platform.js +413 -0
  1042. package/plugins/repo-map/lib/platform/detection-configs.js +93 -0
  1043. package/plugins/repo-map/lib/platform/state-dir.js +132 -0
  1044. package/plugins/repo-map/lib/platform/verify-tools.js +182 -0
  1045. package/plugins/repo-map/lib/repo-map/cache.js +152 -0
  1046. package/plugins/repo-map/lib/repo-map/index.js +222 -0
  1047. package/plugins/repo-map/lib/repo-map/installer.js +212 -0
  1048. package/plugins/repo-map/lib/repo-map/queries/go.js +27 -0
  1049. package/plugins/repo-map/lib/repo-map/queries/index.js +100 -0
  1050. package/plugins/repo-map/lib/repo-map/queries/java.js +38 -0
  1051. package/plugins/repo-map/lib/repo-map/queries/javascript.js +55 -0
  1052. package/plugins/repo-map/lib/repo-map/queries/python.js +24 -0
  1053. package/plugins/repo-map/lib/repo-map/queries/rust.js +73 -0
  1054. package/plugins/repo-map/lib/repo-map/queries/typescript.js +38 -0
  1055. package/plugins/repo-map/lib/repo-map/runner.js +1165 -0
  1056. package/plugins/repo-map/lib/repo-map/updater.js +474 -0
  1057. package/plugins/repo-map/lib/repo-map/usage-analyzer.js +407 -0
  1058. package/plugins/repo-map/lib/schemas/plugin-manifest.schema.json +57 -0
  1059. package/plugins/repo-map/lib/schemas/validator.js +247 -0
  1060. package/plugins/repo-map/lib/sources/custom-handler.js +199 -0
  1061. package/plugins/repo-map/lib/sources/policy-questions.js +246 -0
  1062. package/plugins/repo-map/lib/sources/source-cache.js +165 -0
  1063. package/plugins/repo-map/lib/state/workflow-state.js +575 -0
  1064. package/plugins/repo-map/lib/types/agent-frontmatter.d.ts +134 -0
  1065. package/plugins/repo-map/lib/types/command-frontmatter.d.ts +107 -0
  1066. package/plugins/repo-map/lib/types/hook-frontmatter.d.ts +115 -0
  1067. package/plugins/repo-map/lib/types/index.d.ts +84 -0
  1068. package/plugins/repo-map/lib/types/plugin-manifest.d.ts +102 -0
  1069. package/plugins/repo-map/lib/types/skill-frontmatter.d.ts +89 -0
  1070. package/plugins/repo-map/lib/utils/atomic-write.js +94 -0
  1071. package/plugins/repo-map/lib/utils/cache-manager.js +159 -0
  1072. package/plugins/repo-map/lib/utils/context-optimizer.js +300 -0
  1073. package/plugins/repo-map/lib/utils/deprecation.js +37 -0
  1074. package/plugins/repo-map/lib/utils/shell-escape.js +88 -0
  1075. package/plugins/repo-map/skills/repo-mapping/SKILL.md +83 -0
  1076. package/plugins/ship/.claude-plugin/plugin.json +21 -0
  1077. package/plugins/ship/commands/ship-ci-review-loop.md +472 -0
  1078. package/plugins/ship/commands/ship-deployment.md +335 -0
  1079. package/plugins/ship/commands/ship-error-handling.md +258 -0
  1080. package/plugins/ship/commands/ship.md +492 -0
  1081. package/plugins/ship/lib/adapter-transforms.js +278 -0
  1082. package/plugins/ship/lib/collectors/codebase.js +392 -0
  1083. package/plugins/ship/lib/collectors/docs-patterns.js +713 -0
  1084. package/plugins/ship/lib/collectors/documentation.js +219 -0
  1085. package/plugins/ship/lib/collectors/github.js +266 -0
  1086. package/plugins/ship/lib/collectors/index.js +126 -0
  1087. package/plugins/ship/lib/config/index.js +14 -0
  1088. package/plugins/ship/lib/cross-platform/index.js +539 -0
  1089. package/plugins/ship/lib/discovery/index.js +352 -0
  1090. package/plugins/ship/lib/drift-detect/collectors.js +37 -0
  1091. package/plugins/ship/lib/enhance/agent-analyzer.js +421 -0
  1092. package/plugins/ship/lib/enhance/agent-patterns.js +571 -0
  1093. package/plugins/ship/lib/enhance/auto-suppression.js +622 -0
  1094. package/plugins/ship/lib/enhance/benchmark.js +417 -0
  1095. package/plugins/ship/lib/enhance/cross-file-analyzer.js +930 -0
  1096. package/plugins/ship/lib/enhance/cross-file-patterns.js +370 -0
  1097. package/plugins/ship/lib/enhance/docs-analyzer.js +325 -0
  1098. package/plugins/ship/lib/enhance/docs-patterns.js +671 -0
  1099. package/plugins/ship/lib/enhance/fixer.js +721 -0
  1100. package/plugins/ship/lib/enhance/hook-analyzer.js +135 -0
  1101. package/plugins/ship/lib/enhance/hook-patterns.js +40 -0
  1102. package/plugins/ship/lib/enhance/index.js +127 -0
  1103. package/plugins/ship/lib/enhance/plugin-analyzer.js +402 -0
  1104. package/plugins/ship/lib/enhance/plugin-patterns.js +326 -0
  1105. package/plugins/ship/lib/enhance/projectmemory-analyzer.js +551 -0
  1106. package/plugins/ship/lib/enhance/projectmemory-patterns.js +617 -0
  1107. package/plugins/ship/lib/enhance/prompt-analyzer.js +457 -0
  1108. package/plugins/ship/lib/enhance/prompt-patterns.js +1484 -0
  1109. package/plugins/ship/lib/enhance/reporter.js +1348 -0
  1110. package/plugins/ship/lib/enhance/security-patterns.js +284 -0
  1111. package/plugins/ship/lib/enhance/skill-analyzer.js +182 -0
  1112. package/plugins/ship/lib/enhance/skill-patterns.js +147 -0
  1113. package/plugins/ship/lib/enhance/suppression.js +352 -0
  1114. package/plugins/ship/lib/enhance/tool-patterns.js +373 -0
  1115. package/plugins/ship/lib/index.js +270 -0
  1116. package/plugins/ship/lib/patterns/cli-enhancers.js +611 -0
  1117. package/plugins/ship/lib/patterns/pipeline.js +948 -0
  1118. package/plugins/ship/lib/patterns/review-patterns.js +558 -0
  1119. package/plugins/ship/lib/patterns/slop-analyzers.js +2305 -0
  1120. package/plugins/ship/lib/patterns/slop-patterns.js +1187 -0
  1121. package/plugins/ship/lib/perf/analyzer/index.js +22 -0
  1122. package/plugins/ship/lib/perf/argument-parser.js +105 -0
  1123. package/plugins/ship/lib/perf/baseline-comparator.js +50 -0
  1124. package/plugins/ship/lib/perf/baseline-store.js +127 -0
  1125. package/plugins/ship/lib/perf/benchmark-runner.js +399 -0
  1126. package/plugins/ship/lib/perf/breaking-point-finder.js +52 -0
  1127. package/plugins/ship/lib/perf/breaking-point-runner.js +60 -0
  1128. package/plugins/ship/lib/perf/checkpoint.js +123 -0
  1129. package/plugins/ship/lib/perf/code-paths.js +86 -0
  1130. package/plugins/ship/lib/perf/consolidation.js +37 -0
  1131. package/plugins/ship/lib/perf/constraint-runner.js +71 -0
  1132. package/plugins/ship/lib/perf/experiment-runner.js +32 -0
  1133. package/plugins/ship/lib/perf/index.js +41 -0
  1134. package/plugins/ship/lib/perf/investigation-state.js +875 -0
  1135. package/plugins/ship/lib/perf/optimization-runner.js +79 -0
  1136. package/plugins/ship/lib/perf/profilers/go.js +22 -0
  1137. package/plugins/ship/lib/perf/profilers/index.js +46 -0
  1138. package/plugins/ship/lib/perf/profilers/java.js +23 -0
  1139. package/plugins/ship/lib/perf/profilers/node.js +27 -0
  1140. package/plugins/ship/lib/perf/profilers/python.js +23 -0
  1141. package/plugins/ship/lib/perf/profilers/rust.js +23 -0
  1142. package/plugins/ship/lib/perf/profiling-runner.js +56 -0
  1143. package/plugins/ship/lib/perf/schemas.js +140 -0
  1144. package/plugins/ship/lib/platform/detect-platform.js +413 -0
  1145. package/plugins/ship/lib/platform/detection-configs.js +93 -0
  1146. package/plugins/ship/lib/platform/state-dir.js +132 -0
  1147. package/plugins/ship/lib/platform/verify-tools.js +182 -0
  1148. package/plugins/ship/lib/repo-map/cache.js +152 -0
  1149. package/plugins/ship/lib/repo-map/index.js +222 -0
  1150. package/plugins/ship/lib/repo-map/installer.js +212 -0
  1151. package/plugins/ship/lib/repo-map/queries/go.js +27 -0
  1152. package/plugins/ship/lib/repo-map/queries/index.js +100 -0
  1153. package/plugins/ship/lib/repo-map/queries/java.js +38 -0
  1154. package/plugins/ship/lib/repo-map/queries/javascript.js +55 -0
  1155. package/plugins/ship/lib/repo-map/queries/python.js +24 -0
  1156. package/plugins/ship/lib/repo-map/queries/rust.js +73 -0
  1157. package/plugins/ship/lib/repo-map/queries/typescript.js +38 -0
  1158. package/plugins/ship/lib/repo-map/runner.js +1165 -0
  1159. package/plugins/ship/lib/repo-map/updater.js +474 -0
  1160. package/plugins/ship/lib/repo-map/usage-analyzer.js +407 -0
  1161. package/plugins/ship/lib/schemas/plugin-manifest.schema.json +57 -0
  1162. package/plugins/ship/lib/schemas/validator.js +247 -0
  1163. package/plugins/ship/lib/sources/custom-handler.js +199 -0
  1164. package/plugins/ship/lib/sources/policy-questions.js +246 -0
  1165. package/plugins/ship/lib/sources/source-cache.js +165 -0
  1166. package/plugins/ship/lib/state/workflow-state.js +575 -0
  1167. package/plugins/ship/lib/types/agent-frontmatter.d.ts +134 -0
  1168. package/plugins/ship/lib/types/command-frontmatter.d.ts +107 -0
  1169. package/plugins/ship/lib/types/hook-frontmatter.d.ts +115 -0
  1170. package/plugins/ship/lib/types/index.d.ts +84 -0
  1171. package/plugins/ship/lib/types/plugin-manifest.d.ts +102 -0
  1172. package/plugins/ship/lib/types/skill-frontmatter.d.ts +89 -0
  1173. package/plugins/ship/lib/utils/atomic-write.js +94 -0
  1174. package/plugins/ship/lib/utils/cache-manager.js +159 -0
  1175. package/plugins/ship/lib/utils/context-optimizer.js +300 -0
  1176. package/plugins/ship/lib/utils/deprecation.js +37 -0
  1177. package/plugins/ship/lib/utils/shell-escape.js +88 -0
  1178. package/plugins/sync-docs/.claude-plugin/plugin.json +20 -0
  1179. package/plugins/sync-docs/agents/sync-docs-agent.md +154 -0
  1180. package/plugins/sync-docs/commands/sync-docs.md +186 -0
  1181. package/plugins/sync-docs/lib/adapter-transforms.js +278 -0
  1182. package/plugins/sync-docs/lib/collectors/codebase.js +392 -0
  1183. package/plugins/sync-docs/lib/collectors/docs-patterns.js +713 -0
  1184. package/plugins/sync-docs/lib/collectors/documentation.js +219 -0
  1185. package/plugins/sync-docs/lib/collectors/github.js +266 -0
  1186. package/plugins/sync-docs/lib/collectors/index.js +126 -0
  1187. package/plugins/sync-docs/lib/config/index.js +14 -0
  1188. package/plugins/sync-docs/lib/cross-platform/index.js +539 -0
  1189. package/plugins/sync-docs/lib/discovery/index.js +352 -0
  1190. package/plugins/sync-docs/lib/drift-detect/collectors.js +37 -0
  1191. package/plugins/sync-docs/lib/enhance/agent-analyzer.js +421 -0
  1192. package/plugins/sync-docs/lib/enhance/agent-patterns.js +571 -0
  1193. package/plugins/sync-docs/lib/enhance/auto-suppression.js +622 -0
  1194. package/plugins/sync-docs/lib/enhance/benchmark.js +417 -0
  1195. package/plugins/sync-docs/lib/enhance/cross-file-analyzer.js +930 -0
  1196. package/plugins/sync-docs/lib/enhance/cross-file-patterns.js +370 -0
  1197. package/plugins/sync-docs/lib/enhance/docs-analyzer.js +325 -0
  1198. package/plugins/sync-docs/lib/enhance/docs-patterns.js +671 -0
  1199. package/plugins/sync-docs/lib/enhance/fixer.js +721 -0
  1200. package/plugins/sync-docs/lib/enhance/hook-analyzer.js +135 -0
  1201. package/plugins/sync-docs/lib/enhance/hook-patterns.js +40 -0
  1202. package/plugins/sync-docs/lib/enhance/index.js +127 -0
  1203. package/plugins/sync-docs/lib/enhance/plugin-analyzer.js +402 -0
  1204. package/plugins/sync-docs/lib/enhance/plugin-patterns.js +326 -0
  1205. package/plugins/sync-docs/lib/enhance/projectmemory-analyzer.js +551 -0
  1206. package/plugins/sync-docs/lib/enhance/projectmemory-patterns.js +617 -0
  1207. package/plugins/sync-docs/lib/enhance/prompt-analyzer.js +457 -0
  1208. package/plugins/sync-docs/lib/enhance/prompt-patterns.js +1484 -0
  1209. package/plugins/sync-docs/lib/enhance/reporter.js +1348 -0
  1210. package/plugins/sync-docs/lib/enhance/security-patterns.js +284 -0
  1211. package/plugins/sync-docs/lib/enhance/skill-analyzer.js +182 -0
  1212. package/plugins/sync-docs/lib/enhance/skill-patterns.js +147 -0
  1213. package/plugins/sync-docs/lib/enhance/suppression.js +352 -0
  1214. package/plugins/sync-docs/lib/enhance/tool-patterns.js +373 -0
  1215. package/plugins/sync-docs/lib/index.js +270 -0
  1216. package/plugins/sync-docs/lib/patterns/cli-enhancers.js +611 -0
  1217. package/plugins/sync-docs/lib/patterns/pipeline.js +948 -0
  1218. package/plugins/sync-docs/lib/patterns/review-patterns.js +558 -0
  1219. package/plugins/sync-docs/lib/patterns/slop-analyzers.js +2305 -0
  1220. package/plugins/sync-docs/lib/patterns/slop-patterns.js +1187 -0
  1221. package/plugins/sync-docs/lib/perf/analyzer/index.js +22 -0
  1222. package/plugins/sync-docs/lib/perf/argument-parser.js +105 -0
  1223. package/plugins/sync-docs/lib/perf/baseline-comparator.js +50 -0
  1224. package/plugins/sync-docs/lib/perf/baseline-store.js +127 -0
  1225. package/plugins/sync-docs/lib/perf/benchmark-runner.js +399 -0
  1226. package/plugins/sync-docs/lib/perf/breaking-point-finder.js +52 -0
  1227. package/plugins/sync-docs/lib/perf/breaking-point-runner.js +60 -0
  1228. package/plugins/sync-docs/lib/perf/checkpoint.js +123 -0
  1229. package/plugins/sync-docs/lib/perf/code-paths.js +86 -0
  1230. package/plugins/sync-docs/lib/perf/consolidation.js +37 -0
  1231. package/plugins/sync-docs/lib/perf/constraint-runner.js +71 -0
  1232. package/plugins/sync-docs/lib/perf/experiment-runner.js +32 -0
  1233. package/plugins/sync-docs/lib/perf/index.js +41 -0
  1234. package/plugins/sync-docs/lib/perf/investigation-state.js +875 -0
  1235. package/plugins/sync-docs/lib/perf/optimization-runner.js +79 -0
  1236. package/plugins/sync-docs/lib/perf/profilers/go.js +22 -0
  1237. package/plugins/sync-docs/lib/perf/profilers/index.js +46 -0
  1238. package/plugins/sync-docs/lib/perf/profilers/java.js +23 -0
  1239. package/plugins/sync-docs/lib/perf/profilers/node.js +27 -0
  1240. package/plugins/sync-docs/lib/perf/profilers/python.js +23 -0
  1241. package/plugins/sync-docs/lib/perf/profilers/rust.js +23 -0
  1242. package/plugins/sync-docs/lib/perf/profiling-runner.js +56 -0
  1243. package/plugins/sync-docs/lib/perf/schemas.js +140 -0
  1244. package/plugins/sync-docs/lib/platform/detect-platform.js +413 -0
  1245. package/plugins/sync-docs/lib/platform/detection-configs.js +93 -0
  1246. package/plugins/sync-docs/lib/platform/state-dir.js +132 -0
  1247. package/plugins/sync-docs/lib/platform/verify-tools.js +182 -0
  1248. package/plugins/sync-docs/lib/repo-map/cache.js +152 -0
  1249. package/plugins/sync-docs/lib/repo-map/index.js +222 -0
  1250. package/plugins/sync-docs/lib/repo-map/installer.js +212 -0
  1251. package/plugins/sync-docs/lib/repo-map/queries/go.js +27 -0
  1252. package/plugins/sync-docs/lib/repo-map/queries/index.js +100 -0
  1253. package/plugins/sync-docs/lib/repo-map/queries/java.js +38 -0
  1254. package/plugins/sync-docs/lib/repo-map/queries/javascript.js +55 -0
  1255. package/plugins/sync-docs/lib/repo-map/queries/python.js +24 -0
  1256. package/plugins/sync-docs/lib/repo-map/queries/rust.js +73 -0
  1257. package/plugins/sync-docs/lib/repo-map/queries/typescript.js +38 -0
  1258. package/plugins/sync-docs/lib/repo-map/runner.js +1165 -0
  1259. package/plugins/sync-docs/lib/repo-map/updater.js +474 -0
  1260. package/plugins/sync-docs/lib/repo-map/usage-analyzer.js +407 -0
  1261. package/plugins/sync-docs/lib/schemas/plugin-manifest.schema.json +57 -0
  1262. package/plugins/sync-docs/lib/schemas/validator.js +247 -0
  1263. package/plugins/sync-docs/lib/sources/custom-handler.js +199 -0
  1264. package/plugins/sync-docs/lib/sources/policy-questions.js +246 -0
  1265. package/plugins/sync-docs/lib/sources/source-cache.js +165 -0
  1266. package/plugins/sync-docs/lib/state/workflow-state.js +575 -0
  1267. package/plugins/sync-docs/lib/types/agent-frontmatter.d.ts +134 -0
  1268. package/plugins/sync-docs/lib/types/command-frontmatter.d.ts +107 -0
  1269. package/plugins/sync-docs/lib/types/hook-frontmatter.d.ts +115 -0
  1270. package/plugins/sync-docs/lib/types/index.d.ts +84 -0
  1271. package/plugins/sync-docs/lib/types/plugin-manifest.d.ts +102 -0
  1272. package/plugins/sync-docs/lib/types/skill-frontmatter.d.ts +89 -0
  1273. package/plugins/sync-docs/lib/utils/atomic-write.js +94 -0
  1274. package/plugins/sync-docs/lib/utils/cache-manager.js +159 -0
  1275. package/plugins/sync-docs/lib/utils/context-optimizer.js +300 -0
  1276. package/plugins/sync-docs/lib/utils/deprecation.js +37 -0
  1277. package/plugins/sync-docs/lib/utils/shell-escape.js +88 -0
  1278. package/plugins/sync-docs/skills/sync-docs/SKILL.md +351 -0
  1279. package/scripts/bump-version.js +92 -0
  1280. package/scripts/check-hardcoded-paths.js +199 -0
  1281. package/scripts/dev-install.js +493 -0
  1282. package/scripts/expand-templates.js +269 -0
  1283. package/scripts/gen-adapters.js +323 -0
  1284. package/scripts/generate-docs.js +558 -0
  1285. package/scripts/generate-plugin-list.js +20 -0
  1286. package/scripts/migrate-opencode.js +307 -0
  1287. package/scripts/perf/repo-map-create.js +46 -0
  1288. package/scripts/plugins.txt +12 -0
  1289. package/scripts/preflight.js +1263 -0
  1290. package/scripts/scaffold.js +490 -0
  1291. package/scripts/setup-hooks.js +169 -0
  1292. package/scripts/stamp-version.js +175 -0
  1293. package/scripts/test-transform.js +85 -0
  1294. package/scripts/validate-agent-skill-compliance.js +284 -0
  1295. package/scripts/validate-counts.js +457 -0
  1296. package/scripts/validate-cross-platform-docs.js +550 -0
  1297. package/scripts/validate-opencode-install.js +182 -0
  1298. package/site/assets/css/main.css +1525 -0
  1299. package/site/assets/css/tokens.css +493 -0
  1300. package/site/assets/favicon.svg +23 -0
  1301. package/site/assets/js/main.js +801 -0
  1302. package/site/assets/logo.png +0 -0
  1303. package/site/assets/og-image.html +163 -0
  1304. package/site/content.json +453 -0
  1305. package/site/index.html +698 -0
  1306. package/site/ux-spec.md +683 -0
  1307. package/site/version.json +5 -0
  1308. package/templates/agent-snippets/enhance-integration-points.md +6 -0
  1309. package/templates/agent-snippets/enhance-skill-delegation.md +18 -0
  1310. package/templates/agent-snippets/model-choice.md +6 -0
@@ -0,0 +1,2305 @@
1
+ /**
2
+ * Slop Analyzers - Multi-pass analysis functions for slop detection
3
+ *
4
+ * These analyzers handle patterns that require structural code analysis
5
+ * beyond simple regex matching (e.g., doc/code ratio computation).
6
+ *
7
+ * @author Avi Fenesh
8
+ * @license MIT
9
+ */
10
+
11
+ /**
12
+ * Analyze JSDoc-to-function ratio to detect excessive documentation
13
+ *
14
+ * Flags functions where JSDoc block lines exceed maxRatio times the function body lines.
15
+ * This pattern often indicates AI-generated code with verbose, unnecessary documentation.
16
+ *
17
+ * @param {string} content - File content to analyze
18
+ * @param {Object} options - Analysis options
19
+ * @param {number} [options.minFunctionLines=3] - Minimum function body lines to analyze
20
+ * @param {number} [options.maxRatio=3.0] - Maximum allowed doc/code ratio
21
+ * @returns {Array<Object>} Array of violations: { line, docLines, codeLines, ratio }
22
+ */
23
+ function analyzeDocCodeRatio(content, options = {}) {
24
+ const minFunctionLines = options.minFunctionLines || 3;
25
+ const maxRatio = options.maxRatio || 3.0;
26
+ const lang = detectLanguage(options.filePath || '.js');
27
+ const violations = [];
28
+
29
+ const config = getDocCodeConfig(lang);
30
+ if (!config) return violations;
31
+
32
+ if (config.useBraces) {
33
+ return analyzeDocCodeBraceLanguage(content, lang, config, minFunctionLines, maxRatio);
34
+ } else {
35
+ return analyzeDocCodePython(content, minFunctionLines, maxRatio);
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Get language-specific configuration for doc/code ratio detection
41
+ */
42
+ function getDocCodeConfig(lang) {
43
+ const configs = {
44
+ js: {
45
+ useBraces: true,
46
+ // JSDoc: /** ... */ followed by function
47
+ docPatterns: [
48
+ /\/\*\*([\s\S]*?)\*\/\s*(export\s+)?(async\s+)?(?:function\s+(\w+)\s*\([^)]*\)|(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s*)?\([^)]*\)\s*=>)/g,
49
+ ],
50
+ },
51
+ java: {
52
+ useBraces: true,
53
+ // Javadoc: /** ... */ followed by method
54
+ docPatterns: [
55
+ /\/\*\*([\s\S]*?)\*\/\s*(?:@\w+\s*)*(?:public|private|protected)?\s*(?:static\s+)?(?:final\s+)?(?:\w+(?:<[^>]*>)?)\s+(\w+)\s*\([^)]*\)/g,
56
+ ],
57
+ },
58
+ rust: {
59
+ useBraces: true,
60
+ // Rust doc comments: /// or //! lines before fn
61
+ docPatterns: [
62
+ /((?:^\s*\/\/[\/!].*\n)+)\s*(?:pub\s+)?(?:async\s+)?fn\s+(\w+)/gm,
63
+ ],
64
+ },
65
+ go: {
66
+ useBraces: true,
67
+ // Go doc comments: // lines before func
68
+ docPatterns: [
69
+ /((?:^\s*\/\/.*\n)+)\s*func\s+(?:\([^)]+\)\s+)?(\w+)/gm,
70
+ ],
71
+ },
72
+ python: {
73
+ useBraces: false,
74
+ },
75
+ };
76
+ return configs[lang];
77
+ }
78
+
79
+ /**
80
+ * Analyze doc/code ratio for brace-delimited languages (JS, Java, Rust, Go)
81
+ */
82
+ function analyzeDocCodeBraceLanguage(content, lang, config, minFunctionLines, maxRatio) {
83
+ const violations = [];
84
+
85
+ for (const pattern of config.docPatterns) {
86
+ let match;
87
+ pattern.lastIndex = 0;
88
+
89
+ while ((match = pattern.exec(content)) !== null) {
90
+ const docBlock = match[1];
91
+ const docLines = countNonEmptyLines(docBlock);
92
+
93
+ // Find the opening brace after the match
94
+ const afterMatch = match.index + match[0].length;
95
+ const openBraceOffset = content.substring(afterMatch).search(/\{/);
96
+ if (openBraceOffset === -1) continue;
97
+
98
+ const funcStart = afterMatch + openBraceOffset;
99
+ const closingBraceIndex = findMatchingBrace(content, funcStart);
100
+ if (closingBraceIndex === -1) continue;
101
+
102
+ const funcBody = content.substring(funcStart + 1, closingBraceIndex);
103
+ const funcLines = countNonEmptyLines(funcBody);
104
+
105
+ if (funcLines < minFunctionLines) continue;
106
+
107
+ const ratio = docLines / funcLines;
108
+ if (ratio > maxRatio) {
109
+ const lineNumber = countNewlines(content.substring(0, match.index)) + 1;
110
+ const funcName = match[4] || match[5] || 'unknown';
111
+ violations.push({
112
+ line: lineNumber,
113
+ docLines: docLines,
114
+ codeLines: funcLines,
115
+ ratio: parseFloat(ratio.toFixed(2)),
116
+ functionName: funcName
117
+ });
118
+ }
119
+ }
120
+ }
121
+
122
+ return violations;
123
+ }
124
+
125
+ /**
126
+ * Analyze doc/code ratio for Python (indentation-based with docstrings)
127
+ */
128
+ function analyzeDocCodePython(content, minFunctionLines, maxRatio) {
129
+ const violations = [];
130
+ const lines = content.split('\n');
131
+
132
+ const defPattern = /^(\s*)(?:async\s+)?def\s+(\w+)\s*\([^)]*\)\s*(?:->.*)?:\s*$/;
133
+
134
+ for (let i = 0; i < lines.length; i++) {
135
+ const match = defPattern.exec(lines[i]);
136
+ if (!match) continue;
137
+
138
+ const funcIndent = match[1].length;
139
+ const funcName = match[2];
140
+
141
+ // Look for docstring right after def
142
+ let docLines = 0;
143
+ let docEndLine = i + 1;
144
+ if (docEndLine < lines.length) {
145
+ const nextLine = lines[docEndLine].trim();
146
+ if (nextLine.startsWith('"""') || nextLine.startsWith("'''")) {
147
+ const quote = nextLine.substring(0, 3);
148
+ // Single-line docstring?
149
+ if (nextLine.length > 6 && nextLine.endsWith(quote)) {
150
+ docLines = 1;
151
+ docEndLine++;
152
+ } else {
153
+ // Multi-line docstring
154
+ docLines = 1;
155
+ docEndLine++;
156
+ while (docEndLine < lines.length) {
157
+ docLines++;
158
+ if (lines[docEndLine].includes(quote)) {
159
+ docEndLine++;
160
+ break;
161
+ }
162
+ docEndLine++;
163
+ }
164
+ }
165
+ }
166
+ }
167
+
168
+ // Count function body lines (after docstring)
169
+ let codeLines = 0;
170
+ for (let j = docEndLine; j < lines.length; j++) {
171
+ const line = lines[j];
172
+ const trimmed = line.trim();
173
+ if (!trimmed) continue;
174
+
175
+ const lineIndent = line.length - line.trimStart().length;
176
+ if (lineIndent <= funcIndent && trimmed) break;
177
+
178
+ if (!trimmed.startsWith('#')) {
179
+ codeLines++;
180
+ }
181
+ }
182
+
183
+ if (codeLines < minFunctionLines) continue;
184
+
185
+ const ratio = docLines / codeLines;
186
+ if (ratio > maxRatio) {
187
+ violations.push({
188
+ line: i + 1,
189
+ docLines: docLines,
190
+ codeLines: codeLines,
191
+ ratio: parseFloat(ratio.toFixed(2)),
192
+ functionName: funcName
193
+ });
194
+ }
195
+ }
196
+
197
+ return violations;
198
+ }
199
+
200
+ /**
201
+ * Count non-empty lines in a string
202
+ * @param {string} str - String to count lines in
203
+ * @returns {number} Number of non-empty lines
204
+ */
205
+ function countNonEmptyLines(str) {
206
+ return str.split('\n').filter(line => line.trim().length > 0).length;
207
+ }
208
+
209
+ /**
210
+ * Count newlines in a string (for line number calculation)
211
+ * @param {string} str - String to count newlines in
212
+ * @returns {number} Number of newlines (lines - 1 for content before position)
213
+ */
214
+ function countNewlines(str) {
215
+ if (!str) return 0;
216
+ return (str.match(/\n/g) || []).length;
217
+ }
218
+
219
+ /**
220
+ * Find matching closing brace (handles nested braces and string literals)
221
+ *
222
+ * Stops at 5000 characters to prevent runaway parsing on malformed code.
223
+ *
224
+ * @param {string} content - Full file content
225
+ * @param {number} openIndex - Index of opening brace
226
+ * @returns {number} Index of matching closing brace, or -1 if not found
227
+ */
228
+ function findMatchingBrace(content, openIndex) {
229
+ let depth = 1;
230
+ let inString = false;
231
+ let stringChar = '';
232
+ let inTemplateExpr = false;
233
+ let templateExprDepth = 0;
234
+
235
+ // Limit search to prevent runaway parsing
236
+ const maxSearch = Math.min(content.length, openIndex + 5000);
237
+
238
+ for (let i = openIndex + 1; i < maxSearch; i++) {
239
+ const char = content[i];
240
+ const prevChar = i > 0 ? content[i - 1] : '';
241
+
242
+ // Skip single-line comments (must be checked before string handling)
243
+ // Quotes/apostrophes inside comments should not affect string state
244
+ if (!inString && char === '/' && content[i + 1] === '/') {
245
+ const eol = content.indexOf('\n', i);
246
+ i = eol === -1 ? maxSearch : eol;
247
+ continue;
248
+ }
249
+
250
+ // Skip block comments
251
+ if (!inString && char === '/' && content[i + 1] === '*') {
252
+ const endComment = content.indexOf('*/', i + 2);
253
+ i = endComment === -1 ? maxSearch : endComment + 1;
254
+ continue;
255
+ }
256
+
257
+ // Handle template literal expression ${...}
258
+ if (char === '$' && content[i + 1] === '{' && inString && stringChar === '`') {
259
+ inTemplateExpr = true;
260
+ templateExprDepth = 1;
261
+ i++; // Skip the {
262
+ continue;
263
+ }
264
+
265
+ // Inside template expression, track braces separately
266
+ if (inTemplateExpr) {
267
+ if (char === '{') {
268
+ templateExprDepth++;
269
+ } else if (char === '}') {
270
+ templateExprDepth--;
271
+ if (templateExprDepth === 0) {
272
+ inTemplateExpr = false;
273
+ }
274
+ }
275
+ continue;
276
+ }
277
+
278
+ // Track string state (handle escaped quotes)
279
+ if ((char === '"' || char === "'" || char === '`') && prevChar !== '\\') {
280
+ if (inString && char === stringChar) {
281
+ inString = false;
282
+ stringChar = '';
283
+ } else if (!inString) {
284
+ inString = true;
285
+ stringChar = char;
286
+ }
287
+ continue;
288
+ }
289
+
290
+ // Count braces outside strings
291
+ if (!inString) {
292
+ if (char === '{') depth++;
293
+ if (char === '}') depth--;
294
+ if (depth === 0) return i;
295
+ }
296
+ }
297
+
298
+ return -1; // Not found within limit
299
+ }
300
+
301
+ // ============================================================================
302
+ // Verbosity Detection
303
+ // ============================================================================
304
+
305
+ /**
306
+ * Comment syntax patterns for different languages
307
+ * blockLen: length of block comment delimiter (2 for /*, 3 for """)
308
+ */
309
+ const COMMENT_SYNTAX = {
310
+ js: { line: /^\s*\/\//, block: { start: /\/\*/, end: /\*\//, len: 2 } },
311
+ python: { line: /^\s*#/, block: { start: /"""/, end: /"""/, len: 3 } },
312
+ rust: { line: /^\s*\/\//, block: { start: /\/\*/, end: /\*\//, len: 2 } },
313
+ go: { line: /^\s*\/\//, block: { start: /\/\*/, end: /\*\//, len: 2 } }
314
+ };
315
+
316
+ /**
317
+ * Detect language from file extension for comment syntax
318
+ * @param {string} filePath - File path or extension
319
+ * @returns {string} Language key (js, python, rust, go)
320
+ */
321
+ function detectCommentLanguage(filePath) {
322
+ if (!filePath) return 'js';
323
+ const ext = filePath.includes('.') ? filePath.substring(filePath.lastIndexOf('.')) : filePath;
324
+ if (['.py'].includes(ext)) return 'python';
325
+ if (['.rs'].includes(ext)) return 'rust';
326
+ if (['.go'].includes(ext)) return 'go';
327
+ return 'js'; // Default for .js, .ts, .jsx, .tsx, etc.
328
+ }
329
+
330
+ /**
331
+ * Analyze inline comment-to-code ratio within functions
332
+ *
333
+ * Flags functions where inline comment lines exceed maxCommentRatio times the code lines.
334
+ * This pattern detects over-explained code where comments restate what the code does.
335
+ *
336
+ * Different from doc/code ratio:
337
+ * - doc/code ratio: counts JSDoc blocks ABOVE functions
338
+ * - verbosity ratio: counts inline comments WITHIN function bodies
339
+ *
340
+ * @param {string} content - File content to analyze
341
+ * @param {Object} options - Analysis options
342
+ * @param {number} [options.minCodeLines=3] - Minimum code lines to analyze
343
+ * @param {number} [options.maxCommentRatio=2.0] - Maximum allowed comment/code ratio
344
+ * @param {string} [options.filePath] - File path for language detection
345
+ * @returns {Array<Object>} Array of violations: { line, commentLines, codeLines, ratio }
346
+ */
347
+ function analyzeVerbosityRatio(content, options = {}) {
348
+ const minCodeLines = options.minCodeLines || 3;
349
+ const maxCommentRatio = options.maxCommentRatio || 2.0;
350
+ const lang = detectCommentLanguage(options.filePath);
351
+ const violations = [];
352
+
353
+ // Pattern to find function declarations with opening brace
354
+ // Handles: function name(), async function name(), const name = () =>, arrow functions
355
+ const funcPattern = /(export\s+)?(async\s+)?(?:function\s+\w+\s*\([^)]*\)|(?:const|let|var)\s+\w+\s*=\s*(?:async\s*)?\([^)]*\)\s*=>|(?:const|let|var)\s+\w+\s*=\s*(?:async\s+)?function\s*\([^)]*\))/g;
356
+
357
+ let match;
358
+ while ((match = funcPattern.exec(content)) !== null) {
359
+ // Find the opening brace after the function declaration
360
+ const afterMatch = match.index + match[0].length;
361
+ const searchRegion = content.substring(afterMatch, afterMatch + 200); // Look ahead
362
+ const braceMatch = searchRegion.match(/^\s*\{/);
363
+
364
+ if (!braceMatch) continue; // No opening brace found (might be expression body arrow)
365
+
366
+ const funcStart = afterMatch + searchRegion.indexOf('{');
367
+ const closingBraceIndex = findMatchingBrace(content, funcStart);
368
+
369
+ if (closingBraceIndex === -1) continue; // Parsing failed, skip
370
+
371
+ const funcBody = content.substring(funcStart + 1, closingBraceIndex);
372
+
373
+ // Count comment lines and code lines within function body
374
+ const lines = funcBody.split('\n');
375
+ let commentLines = 0;
376
+ let codeLines = 0;
377
+ let inBlockComment = false;
378
+ const commentSyntax = COMMENT_SYNTAX[lang] || COMMENT_SYNTAX.js;
379
+
380
+ for (const line of lines) {
381
+ const trimmed = line.trim();
382
+ if (!trimmed) continue; // Skip empty lines
383
+
384
+ // Handle block comments
385
+ if (inBlockComment) {
386
+ commentLines++;
387
+ if (commentSyntax.block.end.test(trimmed)) {
388
+ inBlockComment = false;
389
+ }
390
+ continue;
391
+ }
392
+
393
+ if (commentSyntax.block.start.test(trimmed)) {
394
+ commentLines++;
395
+ const delimLen = commentSyntax.block.len || 2;
396
+ if (!commentSyntax.block.end.test(trimmed.substring(trimmed.search(commentSyntax.block.start) + delimLen))) {
397
+ inBlockComment = true;
398
+ }
399
+ continue;
400
+ }
401
+
402
+ // Handle line comments
403
+ if (commentSyntax.line.test(trimmed)) {
404
+ commentLines++;
405
+ continue;
406
+ }
407
+
408
+ // It's code (may have trailing comment, but primary purpose is code)
409
+ codeLines++;
410
+ }
411
+
412
+ // Skip if function is too small
413
+ if (codeLines < minCodeLines) continue;
414
+
415
+ const ratio = commentLines / codeLines;
416
+ if (ratio > maxCommentRatio) {
417
+ // Line number is 1-indexed: count newlines before match + 1
418
+ const lineNumber = countNewlines(content.substring(0, match.index)) + 1;
419
+ violations.push({
420
+ line: lineNumber,
421
+ commentLines,
422
+ codeLines,
423
+ ratio: parseFloat(ratio.toFixed(2))
424
+ });
425
+ }
426
+ }
427
+
428
+ return violations;
429
+ }
430
+
431
+ // ============================================================================
432
+ // Over-Engineering Detection
433
+ // ============================================================================
434
+
435
+ /**
436
+ * Standard entry points per language ecosystem
437
+ * Libraries typically re-export from these files
438
+ */
439
+ const ENTRY_POINTS = [
440
+ 'index.js', 'index.ts', 'src/index.js', 'src/index.ts',
441
+ 'lib/index.js', 'lib/index.ts', 'main.js', 'main.ts',
442
+ 'lib.rs', 'src/lib.rs',
443
+ 'main.go',
444
+ '__init__.py', 'src/__init__.py',
445
+ 'Main.java', 'src/Main.java', 'src/main/java/Main.java',
446
+ 'Application.java', 'src/main/java/Application.java',
447
+ 'App.java', 'src/main/java/App.java'
448
+ ];
449
+
450
+ /**
451
+ * Export patterns per language (used by countExportsInContent)
452
+ */
453
+ const EXPORT_PATTERNS = {
454
+ js: [
455
+ /export\s+(function|class|const|let|var|default|async\s+function)/g,
456
+ /export\s*\{[^}]+\}/g, // Named re-exports: export { Foo, Bar }
457
+ /export\s*\*\s*(as\s+\w+\s+)?from/g, // Star re-exports: export * from './foo'
458
+ /module\.exports\s*=/g,
459
+ /exports\.\w+\s*=/g
460
+ ],
461
+ rust: [
462
+ /^pub\s+(fn|struct|enum|mod|type|trait|const|static)/gm
463
+ ],
464
+ go: [
465
+ /^func\s+[A-Z]/gm,
466
+ /^type\s+[A-Z]\w*\s+(struct|interface)/gm,
467
+ /^var\s+[A-Z]/gm,
468
+ /^const\s+[A-Z]/gm
469
+ ],
470
+ python: [
471
+ /__all__\s*=\s*\[/g,
472
+ /^def\s+(?!_)\w+\s*\(/gm, // Public functions (excludes _private)
473
+ /^class\s+[A-Z]\w*[\s:(]/gm
474
+ ],
475
+ java: [
476
+ /^\s*public\s+(?:static\s+)?(?:final\s+)?(?:class|interface|enum)\s+\w+/gm,
477
+ /^\s*public\s+(?:static\s+)?(?:final\s+)?(?:synchronized\s+)?(?:\w+(?:<[^>]*>)?)\s+\w+\s*\(/gm
478
+ ]
479
+ };
480
+
481
+ /**
482
+ * Source file extensions per language
483
+ */
484
+ const SOURCE_EXTENSIONS = {
485
+ js: ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs'],
486
+ rust: ['.rs'],
487
+ go: ['.go'],
488
+ python: ['.py'],
489
+ java: ['.java']
490
+ };
491
+
492
+ /**
493
+ * Directories to exclude from analysis
494
+ */
495
+ const EXCLUDE_DIRS = [
496
+ 'node_modules', 'vendor', 'dist', 'build', 'out', 'target',
497
+ '.git', '.svn', '.hg', '__pycache__', '.pytest_cache',
498
+ 'coverage', '.nyc_output', '.next', '.nuxt', '.cache'
499
+ ];
500
+
501
+ /**
502
+ * Parse .gitignore file and return a matcher function
503
+ * @param {string} repoPath - Repository root path
504
+ * @param {Object} fs - File system module
505
+ * @param {Object} path - Path module
506
+ * @returns {Function|null} Matcher function or null if no .gitignore
507
+ */
508
+ function parseGitignore(repoPath, fs, path) {
509
+ const gitignorePath = path.join(repoPath, '.gitignore');
510
+
511
+ let content;
512
+ try {
513
+ content = fs.readFileSync(gitignorePath, 'utf8');
514
+ } catch {
515
+ return null; // No .gitignore file
516
+ }
517
+
518
+ const patterns = content
519
+ .split('\n')
520
+ .map(line => line.trim())
521
+ .filter(line => line && !line.startsWith('#'))
522
+ .map(rawPattern => {
523
+ let pattern = rawPattern;
524
+
525
+ // Track if pattern is negated
526
+ const negated = pattern.startsWith('!');
527
+ if (negated) pattern = pattern.slice(1);
528
+
529
+ // Track if pattern is directory-only
530
+ const dirOnly = pattern.endsWith('/');
531
+ if (dirOnly) pattern = pattern.slice(0, -1);
532
+
533
+ // Track if pattern is anchored (explicit / at start)
534
+ const anchored = pattern.startsWith('/');
535
+ if (anchored) pattern = pattern.slice(1);
536
+
537
+ // Check if pattern starts with ** (matches any leading path)
538
+ const matchesAnywhere = pattern.startsWith('**/');
539
+
540
+ // Convert gitignore pattern to regex
541
+ // Step 1: Replace globstar patterns with placeholders (before escaping)
542
+ let regexStr = pattern
543
+ .replace(/^\*\*\//, '\x00LEADING\x00')
544
+ .replace(/\/\*\*$/, '\x00TRAILING\x00')
545
+ .replace(/\*\*\//g, '\x00ANYPATH\x00')
546
+ .replace(/\/\*\*/g, '\x00ANYPATH2\x00')
547
+ .replace(/\*\*/g, '\x00STAR2\x00');
548
+
549
+ // Step 2: Escape special regex chars (except * and ?) and handle remaining globs
550
+ regexStr = regexStr
551
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&')
552
+ .replace(/\*/g, '[^/]*')
553
+ .replace(/\?/g, '[^/]');
554
+
555
+ // Step 3: Restore globstar patterns with proper regex
556
+ regexStr = regexStr
557
+ .replace(/\x00LEADING\x00/g, '(?:.*/)?')
558
+ .replace(/\x00TRAILING\x00/g, '(?:/.*)?')
559
+ .replace(/\x00ANYPATH\x00/g, '(?:.*/)?')
560
+ .replace(/\x00ANYPATH2\x00/g, '(?:/.*)?')
561
+ .replace(/\x00STAR2\x00/g, '.*');
562
+
563
+ // Pattern matching rules:
564
+ // - Anchored (starts with /): match from root only
565
+ // - Starts with **: match anywhere (leading ** already handled in regex)
566
+ // - Contains /: match relative to root
567
+ // - Simple name: match anywhere in path
568
+ if (anchored) {
569
+ regexStr = '^' + regexStr;
570
+ } else if (matchesAnywhere) {
571
+ // Leading ** already allows matching anywhere via (?:.*/)? prefix
572
+ regexStr = '^' + regexStr;
573
+ } else if (pattern.includes('/')) {
574
+ regexStr = '^' + regexStr;
575
+ } else {
576
+ // Simple patterns match anywhere
577
+ regexStr = '(?:^|/)' + regexStr;
578
+ }
579
+
580
+ return {
581
+ regex: new RegExp(regexStr + '(?:$|/)'),
582
+ negated,
583
+ dirOnly
584
+ };
585
+ });
586
+
587
+ return function isIgnored(relativePath, isDirectory = false) {
588
+ // Normalize path separators
589
+ const normalized = relativePath.replace(/\\/g, '/');
590
+ let ignored = false;
591
+
592
+ for (const { regex, negated, dirOnly } of patterns) {
593
+ // Skip directory-only patterns for files
594
+ if (dirOnly && !isDirectory) continue;
595
+
596
+ if (regex.test(normalized)) {
597
+ ignored = !negated;
598
+ }
599
+ }
600
+
601
+ return ignored;
602
+ };
603
+ }
604
+
605
+ /**
606
+ * Detect language from file extension
607
+ * @param {string} filePath - Path to file
608
+ * @returns {string} Language key (js, rust, go, python)
609
+ */
610
+ function detectLanguage(filePath) {
611
+ const ext = filePath.substring(filePath.lastIndexOf('.'));
612
+ for (const [lang, exts] of Object.entries(SOURCE_EXTENSIONS)) {
613
+ if (exts.includes(ext)) return lang;
614
+ }
615
+ return 'js'; // Default to JS patterns
616
+ }
617
+
618
+ /**
619
+ * Count exports in file content based on language
620
+ * @param {string} content - File content
621
+ * @param {string} lang - Language key
622
+ * @returns {number} Number of exports detected
623
+ */
624
+ function countExportsInContent(content, lang) {
625
+ const patterns = EXPORT_PATTERNS[lang] || EXPORT_PATTERNS.js;
626
+ let count = 0;
627
+
628
+ for (const pattern of patterns) {
629
+ // Clone pattern to reset lastIndex
630
+ const regex = new RegExp(pattern.source, pattern.flags);
631
+ const matches = content.match(regex);
632
+ if (matches) count += matches.length;
633
+ }
634
+
635
+ return count;
636
+ }
637
+
638
+ /**
639
+ * Check if path should be excluded from analysis
640
+ * @param {string} filePath - Path to check
641
+ * @param {string[]} excludeDirs - Directories to exclude
642
+ * @returns {boolean} True if should be excluded
643
+ */
644
+ function shouldExclude(filePath, excludeDirs = EXCLUDE_DIRS) {
645
+ const parts = filePath.split(/[\\/]/);
646
+ return parts.some(part => excludeDirs.includes(part));
647
+ }
648
+
649
+ /**
650
+ * Check if file is a test file
651
+ * @param {string} filePath - Path to check
652
+ * @returns {boolean} True if test file
653
+ */
654
+ function isTestFile(filePath) {
655
+ const testPatterns = [
656
+ /\.test\.[jt]sx?$/,
657
+ /\.spec\.[jt]sx?$/,
658
+ /_tests?\.(go|rs|py)$/,
659
+ /test_.*\.py$/,
660
+ /__tests__/,
661
+ /tests?\//i
662
+ ];
663
+ return testPatterns.some(p => p.test(filePath));
664
+ }
665
+
666
+ /**
667
+ * Count source files in directory (recursive, excludes tests/vendor by default)
668
+ *
669
+ * @param {string} repoPath - Repository root path
670
+ * @param {Object} options - Options
671
+ * @param {Function} options.readdir - Directory reader (for testing)
672
+ * @param {Function} options.stat - Stat function (for testing)
673
+ * @param {number} options.maxFiles - Maximum files to count (default 10000)
674
+ * @param {boolean} options.includeTests - Include test files (default false)
675
+ * @param {boolean} options.respectGitignore - Respect .gitignore patterns (default true)
676
+ * @returns {Object} { count, files[] }
677
+ */
678
+ function countSourceFiles(repoPath, options = {}) {
679
+ const fs = options.fs || require('fs');
680
+ const path = options.path || require('path');
681
+ const maxFiles = options.maxFiles || 10000;
682
+ const includeTests = options.includeTests || false;
683
+ const respectGitignore = options.respectGitignore !== false;
684
+
685
+ const files = [];
686
+ let count = 0;
687
+ // Pre-compute extension list for performance (avoid recalculation in loop)
688
+ const allExts = Object.values(SOURCE_EXTENSIONS).flat();
689
+
690
+ // Parse .gitignore if enabled
691
+ const isIgnored = respectGitignore ? parseGitignore(repoPath, fs, path) : null;
692
+
693
+ function walk(dir, depth = 0) {
694
+ if (count >= maxFiles) return;
695
+ if (depth > 10) return; // Prevent infinite recursion
696
+
697
+ let entries;
698
+ try {
699
+ entries = fs.readdirSync(dir, { withFileTypes: true });
700
+ } catch {
701
+ return; // Skip unreadable directories
702
+ }
703
+
704
+ for (const entry of entries) {
705
+ if (count >= maxFiles) break;
706
+
707
+ const fullPath = path.join(dir, entry.name);
708
+ const relativePath = path.relative(repoPath, fullPath);
709
+
710
+ if (shouldExclude(relativePath)) continue;
711
+
712
+ // Check gitignore
713
+ if (isIgnored && isIgnored(relativePath, entry.isDirectory())) continue;
714
+
715
+ if (entry.isDirectory()) {
716
+ walk(fullPath, depth + 1);
717
+ } else if (entry.isFile()) {
718
+ const ext = path.extname(entry.name);
719
+
720
+ if (allExts.includes(ext) && (includeTests || !isTestFile(relativePath))) {
721
+ files.push(relativePath);
722
+ count++;
723
+ }
724
+ }
725
+ }
726
+ }
727
+
728
+ walk(repoPath);
729
+ return { count, files };
730
+ }
731
+
732
+ /**
733
+ * Count source lines (excluding comments and blanks)
734
+ *
735
+ * Uses simple heuristics - not a full parser but good enough for metrics.
736
+ * Reads files asynchronously to avoid blocking I/O (PERF-007).
737
+ *
738
+ * @param {string} repoPath - Repository root path
739
+ * @param {Object} options - Options
740
+ * @param {string[]} options.files - Files to count (from countSourceFiles)
741
+ * @param {Object} options.fs - File system module (for testing)
742
+ * @returns {Promise<number>} Total source lines
743
+ */
744
+ async function countSourceLines(repoPath, options = {}) {
745
+ const fs = options.fs || require('fs');
746
+ const fsPromises = fs.promises || require('fs').promises;
747
+ const path = options.path || require('path');
748
+ const files = options.files || countSourceFiles(repoPath, options).files;
749
+
750
+ // Process files in parallel batches to avoid overwhelming the system
751
+ const BATCH_SIZE = 50;
752
+ let totalLines = 0;
753
+
754
+ for (let i = 0; i < files.length; i += BATCH_SIZE) {
755
+ const batch = files.slice(i, i + BATCH_SIZE);
756
+ const results = await Promise.all(
757
+ batch.map(async (file) => {
758
+ try {
759
+ const content = await fsPromises.readFile(path.join(repoPath, file), 'utf8');
760
+ return countLinesInContent(content);
761
+ } catch {
762
+ // Skip unreadable files
763
+ return 0;
764
+ }
765
+ })
766
+ );
767
+ totalLines += results.reduce((sum, count) => sum + count, 0);
768
+ }
769
+
770
+ return totalLines;
771
+ }
772
+
773
+ /**
774
+ * Count source lines in file content (excluding comments and blanks)
775
+ *
776
+ * @param {string} content - File content
777
+ * @returns {number} Source line count
778
+ */
779
+ function countLinesInContent(content) {
780
+ const lines = content.split('\n');
781
+ let count = 0;
782
+ let inBlockComment = false;
783
+
784
+ for (const line of lines) {
785
+ const trimmed = line.trim();
786
+
787
+ // Skip empty lines
788
+ if (!trimmed) continue;
789
+
790
+ // Process line for block comments (handles inline and multi-line)
791
+ let processedLine = trimmed;
792
+
793
+ // Handle block comment state transitions
794
+ if (inBlockComment) {
795
+ const endIdx = processedLine.indexOf('*/');
796
+ if (endIdx !== -1) {
797
+ // Comment ends on this line - keep anything after */
798
+ inBlockComment = false;
799
+ processedLine = processedLine.substring(endIdx + 2).trim();
800
+ } else {
801
+ // Still in block comment
802
+ continue;
803
+ }
804
+ }
805
+
806
+ // Check for block comment start (may also end on same line)
807
+ const startIdx = processedLine.indexOf('/*');
808
+ if (startIdx !== -1) {
809
+ const beforeComment = processedLine.substring(0, startIdx).trim();
810
+ const afterStart = processedLine.substring(startIdx + 2);
811
+ const endIdx = afterStart.indexOf('*/');
812
+
813
+ if (endIdx !== -1) {
814
+ // Single-line block comment: /* ... */
815
+ processedLine = beforeComment + ' ' + afterStart.substring(endIdx + 2).trim();
816
+ processedLine = processedLine.trim();
817
+ } else {
818
+ // Block comment starts but doesn't end
819
+ inBlockComment = true;
820
+ processedLine = beforeComment;
821
+ }
822
+ }
823
+
824
+ // Skip if nothing left after removing comments
825
+ if (!processedLine) continue;
826
+
827
+ // Skip single-line comments
828
+ if (processedLine.startsWith('//') || processedLine.startsWith('#')) continue;
829
+
830
+ // Skip Python/Rust doc comments that span the whole line
831
+ if (processedLine.startsWith('///') || processedLine.startsWith('"""') || processedLine.startsWith("'''")) continue;
832
+
833
+ count++;
834
+ }
835
+
836
+ return count;
837
+ }
838
+
839
+ /**
840
+ * Count exports from entry points
841
+ *
842
+ * Scans standard entry points (index.js, lib.rs, etc.) for export statements.
843
+ * Falls back to scanning all src/ if no entry points found.
844
+ *
845
+ * @param {string} repoPath - Repository root path
846
+ * @param {Object} options - Options
847
+ * @param {Function} options.readFile - File reader (for testing)
848
+ * @returns {Object} { count, method, entryPoints[] }
849
+ */
850
+ function countEntryPointExports(repoPath, options = {}) {
851
+ const fs = options.fs || require('fs');
852
+ const path = options.path || require('path');
853
+
854
+ const foundEntries = [];
855
+ let count = 0;
856
+
857
+ // Try standard entry points
858
+ for (const entry of ENTRY_POINTS) {
859
+ const fullPath = path.join(repoPath, entry);
860
+ try {
861
+ const stat = fs.statSync(fullPath);
862
+ if (stat.isFile()) {
863
+ const content = fs.readFileSync(fullPath, 'utf8');
864
+ const lang = detectLanguage(entry);
865
+ const exports = countExportsInContent(content, lang);
866
+ if (exports > 0) {
867
+ foundEntries.push(entry);
868
+ count += exports;
869
+ }
870
+ }
871
+ } catch {
872
+ // File doesn't exist, try next
873
+ }
874
+ }
875
+
876
+ if (count > 0) {
877
+ return { count, method: 'entry-points', entryPoints: foundEntries };
878
+ }
879
+
880
+ // Fallback: scan src/ for all exports
881
+ const srcDir = path.join(repoPath, 'src');
882
+ try {
883
+ const srcStat = fs.statSync(srcDir);
884
+ if (srcStat.isDirectory()) {
885
+ const { files } = countSourceFiles(srcDir, options);
886
+ for (const file of files) {
887
+ try {
888
+ const content = fs.readFileSync(path.join(srcDir, file), 'utf8');
889
+ const lang = detectLanguage(file);
890
+ count += countExportsInContent(content, lang);
891
+ } catch {
892
+ // Skip unreadable
893
+ }
894
+ }
895
+ if (count > 0) {
896
+ return { count, method: 'src-scan', entryPoints: ['src/'] };
897
+ }
898
+ }
899
+ } catch {
900
+ // No src/ directory
901
+ }
902
+
903
+ // Final fallback
904
+ return { count: 1, method: 'fallback', entryPoints: [] };
905
+ }
906
+
907
+ /**
908
+ * Get maximum directory depth in a path
909
+ *
910
+ * @param {string} repoPath - Repository root path
911
+ * @param {string} startDir - Directory to start from (e.g., 'src')
912
+ * @param {Object} options - Options
913
+ * @returns {number} Maximum depth (0 if startDir doesn't exist)
914
+ */
915
+ function getMaxDirectoryDepth(repoPath, startDir = 'src', options = {}) {
916
+ const fs = options.fs || require('fs');
917
+ const path = options.path || require('path');
918
+
919
+ const rootDir = path.join(repoPath, startDir);
920
+ let maxDepth = 0;
921
+
922
+ function walk(dir, depth) {
923
+ if (depth > maxDepth) maxDepth = depth;
924
+ if (depth > 20) return; // Safety limit
925
+
926
+ try {
927
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
928
+ for (const entry of entries) {
929
+ if (entry.isDirectory() && !shouldExclude(entry.name)) {
930
+ walk(path.join(dir, entry.name), depth + 1);
931
+ }
932
+ }
933
+ } catch {
934
+ // Skip unreadable
935
+ }
936
+ }
937
+
938
+ try {
939
+ const stat = fs.statSync(rootDir);
940
+ if (stat.isDirectory()) {
941
+ walk(rootDir, 1);
942
+ }
943
+ } catch {
944
+ return 0;
945
+ }
946
+
947
+ return maxDepth;
948
+ }
949
+
950
+ /**
951
+ * Analyze over-engineering metrics for a repository
952
+ *
953
+ * Detects three signals of over-engineering:
954
+ * 1. File-to-export ratio > 20x
955
+ * 2. Lines-per-export > 500:1
956
+ * 3. Directory depth > 4 levels
957
+ *
958
+ * @param {string} repoPath - Repository root path
959
+ * @param {Object} options - Analysis options
960
+ * @param {number} [options.fileRatioThreshold=20] - Max files per export
961
+ * @param {number} [options.linesPerExportThreshold=500] - Max lines per export
962
+ * @param {number} [options.depthThreshold=4] - Max directory depth
963
+ * @returns {Promise<Object>} Analysis results with violations
964
+ */
965
+ async function analyzeOverEngineering(repoPath, options = {}) {
966
+ const fileRatioThreshold = options.fileRatioThreshold || 20;
967
+ const linesPerExportThreshold = options.linesPerExportThreshold || 500;
968
+ const depthThreshold = options.depthThreshold || 4;
969
+
970
+ const violations = [];
971
+
972
+ // Count source files
973
+ const { count: sourceFileCount, files } = countSourceFiles(repoPath, options);
974
+
975
+ // Count exports from entry points
976
+ const { count: exportCount, method: exportMethod, entryPoints } = countEntryPointExports(repoPath, options);
977
+
978
+ // Calculate file-to-export ratio
979
+ const fileRatio = sourceFileCount / Math.max(exportCount, 1);
980
+ if (fileRatio > fileRatioThreshold) {
981
+ violations.push({
982
+ type: 'file_proliferation',
983
+ value: `${sourceFileCount} files / ${exportCount} exports = ${fileRatio.toFixed(1)}x`,
984
+ threshold: `${fileRatioThreshold}x`,
985
+ severity: fileRatio > fileRatioThreshold * 2 ? 'high' : 'medium',
986
+ details: { sourceFileCount, exportCount, fileRatio, exportMethod }
987
+ });
988
+ }
989
+
990
+ // Count source lines (async to avoid blocking I/O - PERF-007)
991
+ const totalLines = await countSourceLines(repoPath, { ...options, files });
992
+
993
+ // Calculate lines-per-export ratio
994
+ const linesPerExport = totalLines / Math.max(exportCount, 1);
995
+ if (linesPerExport > linesPerExportThreshold) {
996
+ violations.push({
997
+ type: 'code_density',
998
+ value: `${totalLines} lines / ${exportCount} exports = ${Math.round(linesPerExport)}:1`,
999
+ threshold: `${linesPerExportThreshold}:1`,
1000
+ severity: linesPerExport > linesPerExportThreshold * 2 ? 'high' : 'medium',
1001
+ details: { totalLines, exportCount, linesPerExport }
1002
+ });
1003
+ }
1004
+
1005
+ // Get directory depth
1006
+ const maxDepth = getMaxDirectoryDepth(repoPath, 'src', options);
1007
+ if (maxDepth > depthThreshold) {
1008
+ violations.push({
1009
+ type: 'directory_depth',
1010
+ value: `${maxDepth} levels`,
1011
+ threshold: `${depthThreshold} levels`,
1012
+ severity: maxDepth > depthThreshold + 2 ? 'high' : 'medium',
1013
+ details: { maxDepth }
1014
+ });
1015
+ }
1016
+
1017
+ return {
1018
+ metrics: {
1019
+ sourceFiles: sourceFileCount,
1020
+ exports: exportCount,
1021
+ exportMethod,
1022
+ entryPoints,
1023
+ totalLines,
1024
+ directoryDepth: maxDepth,
1025
+ fileRatio: parseFloat(fileRatio.toFixed(2)),
1026
+ linesPerExport: Math.round(linesPerExport)
1027
+ },
1028
+ violations,
1029
+ verdict: violations.length > 0
1030
+ ? (violations.some(v => v.severity === 'high') ? 'HIGH' : 'MEDIUM')
1031
+ : 'OK'
1032
+ };
1033
+ }
1034
+
1035
+ // ============================================================================
1036
+ // Infrastructure Without Implementation Detection
1037
+ // Detects infrastructure components that are set up but never used
1038
+ // ============================================================================
1039
+
1040
+ /**
1041
+ * Common infrastructure component suffixes that indicate setup/configuration
1042
+ * These naming patterns typically indicate infrastructure components
1043
+ */
1044
+ const INFRASTRUCTURE_SUFFIXES = [
1045
+ 'Client', 'Connection', 'Pool', 'Service', 'Provider',
1046
+ 'Manager', 'Factory', 'Repository', 'Gateway', 'Adapter',
1047
+ 'Handler', 'Broker', 'Queue', 'Cache', 'Store',
1048
+ 'Transport', 'Channel', 'Socket', 'Server', 'Database'
1049
+ ];
1050
+
1051
+ // Pattern for detecting overly generic variable names to skip
1052
+ const GENERIC_VAR_PATTERN = /^[ijkxy]$/;
1053
+
1054
+ /**
1055
+ * Common setup/initialization verbs that indicate infrastructure creation
1056
+ */
1057
+ const SETUP_VERBS = [
1058
+ 'create', 'connect', 'init', 'initialize', 'setup',
1059
+ 'configure', 'establish', 'open', 'start', 'new',
1060
+ 'build', 'make', 'construct', 'instantiate', 'spawn'
1061
+ ];
1062
+
1063
+ /**
1064
+ * Language-specific patterns for instantiation/initialization
1065
+ * These patterns detect when infrastructure components are created
1066
+ */
1067
+ const INSTANTIATION_PATTERNS = {
1068
+ js: [
1069
+ // new Class() instantiation
1070
+ /(?:const|let|var)\s+(\w+)\s*=\s*new\s+(\w+(?:Client|Connection|Pool|Service|Provider|Manager|Factory|Repository|Gateway|Adapter|Handler|Broker|Queue|Cache|Store|Transport|Channel|Socket|Server|Database))/g,
1071
+ // Factory/builder pattern: createXxx(), Xxx.create()
1072
+ /(?:const|let|var)\s+(\w+)\s*=\s*(?:await\s+)?(?:create|connect|init|initialize|setup)(\w+)/gi,
1073
+ // Method call pattern: thing.connect(), thing.initialize()
1074
+ /(?:const|let|var)\s+(\w+)\s*=\s*(?:await\s+)?\w+\.(?:create|connect|init|initialize|setup|open|start)\(/gi
1075
+ ],
1076
+ python: [
1077
+ // Class instantiation: client = SomeClient()
1078
+ /(\w+)\s*=\s*(\w+(?:Client|Connection|Pool|Service|Provider|Manager|Factory|Repository|Gateway|Adapter|Handler|Broker|Queue|Cache|Store|Transport|Channel|Socket|Server|Database))\(/gm,
1079
+ // Module.Class pattern: client = module.RedisClient()
1080
+ /(\w+)\s*=\s*\w+\.(\w+(?:Client|Connection|Pool|Service|Provider|Manager|Factory|Repository|Gateway|Adapter|Handler|Broker|Queue|Cache|Store|Transport|Channel|Socket|Server|Database))\(/gm,
1081
+ // Factory pattern: client = create_client()
1082
+ /(\w+)\s*=\s*(?:create|connect|init|initialize|setup)_(\w+)\(/gm,
1083
+ // Async patterns: client = await create_client()
1084
+ /(\w+)\s*=\s*await\s+(?:create|connect|init|initialize|setup)_(\w+)\(/gm
1085
+ ],
1086
+ go: [
1087
+ // New* function pattern: client := NewClient()
1088
+ /(\w+)\s*:=\s*(?:New|Create|Connect|Init|Setup)(\w+)\(/g,
1089
+ // Module.New* pattern: client := redis.NewClient()
1090
+ /(\w+)\s*:=\s*\w+\.(?:New|Create|Connect|Init|Setup)(\w+)\(/g,
1091
+ // Variable declaration: var client = NewClient()
1092
+ /var\s+(\w+)\s+.*=\s*(?:New|Create|Connect|Init|Setup)(\w+)\(/g,
1093
+ // Struct literal with suffix: client := &RedisClient{}
1094
+ /(\w+)\s*:=\s*&(\w+(?:Client|Connection|Pool|Service|Provider|Manager|Factory|Repository|Gateway|Adapter|Handler|Broker|Queue|Cache|Store|Transport|Channel|Socket|Server|Database))\{/g
1095
+ ],
1096
+ rust: [
1097
+ // ::new() constructor: let client = Client::new()
1098
+ /let\s+(?:mut\s+)?(\w+)\s*=\s*(\w*(?:Client|Connection|Pool|Service|Provider|Manager|Factory|Repository|Gateway|Adapter|Handler|Broker|Queue|Cache|Store|Transport|Channel|Socket|Server|Database))::(?:new|create|connect|init|build)\(/g,
1099
+ // Builder pattern: let client = ClientBuilder::new().build()
1100
+ /let\s+(?:mut\s+)?(\w+)\s*=\s*(\w+Builder)::new\(\).*\.build\(\)/g,
1101
+ // From/into patterns: let client = Client::from()
1102
+ /let\s+(?:mut\s+)?(\w+)\s*=\s*(\w*(?:Client|Connection|Pool|Service|Provider|Manager|Factory|Repository|Gateway|Adapter|Handler|Broker|Queue|Cache|Store|Transport|Channel|Socket|Server|Database))::from/g
1103
+ ],
1104
+ java: [
1105
+ // Field/local var: Client client = new Client()
1106
+ /(?:\w+(?:<[^>]*>)?)\s+(\w+)\s*=\s*new\s+(\w+(?:Client|Connection|Pool|Service|Provider|Manager|Factory|Repository|Gateway|Adapter|Handler|Broker|Queue|Cache|Store|Transport|Channel|Socket|Server|Database))(?:<[^>]*>)?\s*\(/g,
1107
+ // Factory pattern: Client client = ClientFactory.create()
1108
+ /(?:\w+(?:<[^>]*>)?)\s+(\w+)\s*=\s*(\w+(?:Factory|Builder))\.(?:create|build|get|new)\w*\(/g,
1109
+ // Builder pattern: Client client = Client.builder().build()
1110
+ /(?:\w+(?:<[^>]*>)?)\s+(\w+)\s*=\s*(\w+)\.builder\(\).*\.build\(\)/g,
1111
+ // Spring/DI injection via constructor or field
1112
+ /@(?:Autowired|Inject)\s+(?:private\s+)?(?:\w+(?:<[^>]*>)?)\s+(\w+)/g
1113
+ ]
1114
+ };
1115
+
1116
+ // ============================================================================
1117
+ // Buzzword Inflation Detection
1118
+ // Detects quality claims in docs/comments without supporting code evidence
1119
+ // ============================================================================
1120
+
1121
+ /**
1122
+ * Default buzzword categories and their associated terms
1123
+ */
1124
+ const BUZZWORD_CATEGORIES = {
1125
+ production: ['production-ready', 'production-grade', 'prod-ready'],
1126
+ enterprise: ['enterprise-grade', 'enterprise-ready', 'enterprise-class'],
1127
+ security: ['secure', 'secure by default', 'security-focused'],
1128
+ scale: ['scalable', 'high-performance', 'performant', 'highly scalable'],
1129
+ reliability: ['battle-tested', 'robust', 'reliable', 'rock-solid'],
1130
+ completeness: ['comprehensive', 'complete', 'full-featured', 'feature-complete']
1131
+ };
1132
+
1133
+ /**
1134
+ * Evidence patterns per buzzword category
1135
+ * Each category maps to evidence types, each with array of regex patterns
1136
+ */
1137
+ const EVIDENCE_PATTERNS = {
1138
+ production: {
1139
+ tests: [/\.test\.[jt]sx?$|\.spec\.[jt]sx?$|__tests__|test_.*\.py$|_test\.go$|_test\.rs$/],
1140
+ errorHandling: [/try\s*\{|catch\s*\(|\.catch\s*\(|except\s*:|if\s+let\s+Err|match.*Err\(/],
1141
+ logging: [/logger\.|\.log\s*\(|console\.error|tracing::|slog\.|log\.(info|warn|error|debug)/i]
1142
+ },
1143
+ enterprise: {
1144
+ auth: [/authenticat|authorization|permission|rbac|acl|role/i],
1145
+ audit: [/audit|track.*event|event.*log|activity.*log/i],
1146
+ rateLimit: [/rate.?limit|throttle|limiter/i]
1147
+ },
1148
+ security: {
1149
+ validation: [/validat|sanitiz|escape|clean|htmlspecialchars/i],
1150
+ auth: [/\bauth\b|token|jwt|session|login|passport/i],
1151
+ encryption: [/encrypt|decrypt|hash|bcrypt|argon|crypto\./i]
1152
+ },
1153
+ scale: {
1154
+ async: [/async\s+|await\s+|Promise|Future|tokio|async_std|goroutine/],
1155
+ cache: [/\bcache\b|redis|memcache|lru/i],
1156
+ pool: [/pool|connection.?pool|thread.?pool/i]
1157
+ },
1158
+ reliability: {
1159
+ tests: [/\.test\.[jt]sx?$|\.spec\.[jt]sx?$|__tests__|test_.*\.py$|_test\.go$|_test\.rs$/],
1160
+ coverage: [/coverage|lcov|nyc|istanbul|codecov/i],
1161
+ errorHandling: [/try\s*\{|catch\s*\(|\.catch\s*\(|except\s*:|if\s+let\s+Err/]
1162
+ },
1163
+ completeness: {
1164
+ edgeCases: [/edge.?case|boundary|corner.?case/i],
1165
+ errorHandling: [/\b(handle|handles|handled|handling)\s+(all\s+)?(errors?|exceptions?|failures?)\b/i],
1166
+ documentation: [/\/\*\*|\/\/\/|"""|'''/]
1167
+ }
1168
+ };
1169
+
1170
+ /**
1171
+ * Patterns indicating a positive claim (not TODO/aspirational)
1172
+ */
1173
+ const CLAIM_INDICATORS = [
1174
+ /\bis\s+/i, // "is secure"
1175
+ /\bare\s+/i, // "are production-ready"
1176
+ /\bprovides?\s+/i, // "provides secure"
1177
+ /\boffers?\s+/i, // "offers robust"
1178
+ /\bfeatures?\s+/i, // "features comprehensive"
1179
+ /\bfully\s+/i, // "fully production-ready"
1180
+ /\b100%\s+/i, // "100% secure"
1181
+ /\bdesigned\s+(for|to\s+be)\s+/i // "designed for security"
1182
+ ];
1183
+
1184
+ /**
1185
+ * Patterns indicating NOT a claim (aspirational/TODO)
1186
+ */
1187
+ const NOT_CLAIM_INDICATORS = [
1188
+ /\bTODO\b/i,
1189
+ /\bFIXME\b/i,
1190
+ /\bshould\s+be\b/i,
1191
+ /\bwill\s+be\b/i,
1192
+ /\bmake\s+(?:it\s+(?:more|less|better)|this\b)/i,
1193
+ /\bneed(s)?\s+to\s+be\b/i,
1194
+ /\bplan(ning)?\s+to\b/i,
1195
+ /\bwant(s)?\s+to\b/i
1196
+ ];
1197
+
1198
+ /**
1199
+ * Escape regex special characters in a string
1200
+ * @param {string} str - String to escape
1201
+ * @returns {string} Escaped string safe for regex
1202
+ */
1203
+ function escapeRegex(str) {
1204
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1205
+ }
1206
+
1207
+ /**
1208
+ * Extract buzzword claims from file content
1209
+ *
1210
+ * @param {string} content - File content
1211
+ * @param {string} filePath - Path to file (for reporting)
1212
+ * @param {Object} buzzwordCategories - Buzzword category mappings
1213
+ * @returns {Array<Object>} Array of claims with line, buzzword, category, isPositiveClaim
1214
+ */
1215
+ function extractClaims(content, filePath, buzzwordCategories = BUZZWORD_CATEGORIES) {
1216
+ const claims = [];
1217
+ const lines = content.split('\n');
1218
+
1219
+ // Build single regex from all buzzwords and reverse map for category lookup
1220
+ const allBuzzwords = [];
1221
+ const buzzwordToCategory = new Map();
1222
+ for (const [category, buzzwords] of Object.entries(buzzwordCategories)) {
1223
+ for (const buzzword of buzzwords) {
1224
+ allBuzzwords.push(escapeRegex(buzzword));
1225
+ buzzwordToCategory.set(buzzword.toLowerCase(), { category, buzzword });
1226
+ }
1227
+ }
1228
+ const combinedRegex = new RegExp(`\\b(${allBuzzwords.join('|')})\\b`, 'gi');
1229
+
1230
+ for (let i = 0; i < lines.length; i++) {
1231
+ const line = lines[i];
1232
+
1233
+ // Find all buzzword matches in this line
1234
+ const matches = [...line.matchAll(combinedRegex)];
1235
+ if (matches.length === 0) continue;
1236
+
1237
+ // Check claim indicators once per line (only if matches found)
1238
+ const hasNotClaimIndicator = NOT_CLAIM_INDICATORS.some(p => p.test(line));
1239
+ const hasClaimIndicator = CLAIM_INDICATORS.some(p => p.test(line));
1240
+ const isPositiveClaim = hasClaimIndicator && !hasNotClaimIndicator;
1241
+
1242
+ for (const match of matches) {
1243
+ const matchedText = match[1].toLowerCase();
1244
+ const mapping = buzzwordToCategory.get(matchedText);
1245
+ if (!mapping) continue;
1246
+
1247
+ claims.push({
1248
+ line: i + 1,
1249
+ column: match.index,
1250
+ buzzword: mapping.buzzword,
1251
+ category: mapping.category,
1252
+ text: line.trim(),
1253
+ isPositiveClaim,
1254
+ filePath
1255
+ });
1256
+ }
1257
+ }
1258
+
1259
+ return claims;
1260
+ }
1261
+
1262
+ /**
1263
+ * Find files that may contain claims (docs, READMEs, code with comments)
1264
+ *
1265
+ * @param {string} repoPath - Repository root path
1266
+ * @param {Object} options - Options with fs/path overrides
1267
+ * @returns {Array<string>} Array of relative file paths
1268
+ */
1269
+ function findClaimSourceFiles(repoPath, options = {}) {
1270
+ const fs = options.fs || require('fs');
1271
+ const path = options.path || require('path');
1272
+
1273
+ const files = [];
1274
+ const docPatterns = [
1275
+ /README/i,
1276
+ /\.md$/,
1277
+ /docs?\//i,
1278
+ /\.rst$/,
1279
+ /CHANGELOG/i,
1280
+ /\.[jt]sx?$/, // JS/TS files (JSDoc comments)
1281
+ /\.py$/, // Python (docstrings)
1282
+ /\.rs$/, // Rust (doc comments)
1283
+ /\.go$/ // Go (doc comments)
1284
+ ];
1285
+
1286
+ function walk(dir, depth = 0) {
1287
+ if (depth > 5) return; // Limit depth
1288
+ if (files.length > 500) return; // Limit file count
1289
+
1290
+ let entries;
1291
+ try {
1292
+ entries = fs.readdirSync(dir, { withFileTypes: true });
1293
+ } catch {
1294
+ return; // Skip unreadable directories
1295
+ }
1296
+
1297
+ for (const entry of entries) {
1298
+ const fullPath = path.join(dir, entry.name);
1299
+ const relativePath = path.relative(repoPath, fullPath);
1300
+
1301
+ if (shouldExclude(relativePath)) continue;
1302
+
1303
+ if (entry.isDirectory()) {
1304
+ walk(fullPath, depth + 1);
1305
+ } else if (entry.isFile()) {
1306
+ if (docPatterns.some(p => p.test(relativePath))) {
1307
+ files.push(relativePath);
1308
+ }
1309
+ }
1310
+ }
1311
+ }
1312
+
1313
+ walk(repoPath);
1314
+ return files;
1315
+ }
1316
+
1317
+ /**
1318
+ * Check if a regex pattern is for matching file paths (vs file content)
1319
+ * File path patterns typically match file extensions or test directory structures
1320
+ *
1321
+ * @param {RegExp} regex - The pattern to check
1322
+ * @returns {boolean} True if this is a file path pattern
1323
+ */
1324
+ function isFilePathPattern(regex) {
1325
+ const source = regex.source;
1326
+ // File path patterns match file extensions or test directories
1327
+ return (
1328
+ source.includes('\\.[jt]sx?$') || // .js, .ts, .jsx, .tsx
1329
+ source.includes('\\.py$') || // .py
1330
+ source.includes('\\.go$') || // .go
1331
+ source.includes('\\.rs$') || // .rs
1332
+ source.includes('__tests__') || // Jest test directory
1333
+ source.includes('_test\\.') || // Go/Rust test files
1334
+ source.includes('test_.*\\.') || // Python test files
1335
+ source.includes('\\.spec\\.') // Spec files
1336
+ );
1337
+ }
1338
+
1339
+ /**
1340
+ * Search for evidence supporting a buzzword category
1341
+ *
1342
+ * @param {string} repoPath - Repository root path
1343
+ * @param {string} category - Buzzword category to search evidence for
1344
+ * @param {Object} evidencePatterns - Evidence patterns mapping
1345
+ * @param {Array<string>} filesToSearch - Files to search
1346
+ * @param {Object} options - Options with fs/path overrides
1347
+ * @returns {Object} Evidence results: { found[], total, categories{} }
1348
+ */
1349
+ function searchEvidence(repoPath, category, evidencePatterns, filesToSearch, options = {}) {
1350
+ const fs = options.fs || require('fs');
1351
+ const path = options.path || require('path');
1352
+
1353
+ const evidence = {
1354
+ found: [],
1355
+ total: 0,
1356
+ categories: {}
1357
+ };
1358
+
1359
+ // Get evidence patterns for this category
1360
+ const patterns = evidencePatterns[category];
1361
+ if (!patterns) return evidence;
1362
+
1363
+ // Separate path patterns from content patterns for efficiency
1364
+ const pathPatterns = [];
1365
+ const contentPatterns = [];
1366
+ for (const [evidenceType, regexes] of Object.entries(patterns)) {
1367
+ for (const regex of regexes) {
1368
+ if (isFilePathPattern(regex)) {
1369
+ pathPatterns.push({ evidenceType, regex });
1370
+ } else {
1371
+ contentPatterns.push({ evidenceType, regex });
1372
+ }
1373
+ }
1374
+ }
1375
+
1376
+ for (const file of filesToSearch) {
1377
+ // Check path patterns first (no file read needed)
1378
+ for (const { evidenceType, regex } of pathPatterns) {
1379
+ if (regex.test(file)) {
1380
+ if (!evidence.categories[evidenceType]) {
1381
+ evidence.categories[evidenceType] = [];
1382
+ }
1383
+ if (!evidence.categories[evidenceType].includes(file)) {
1384
+ evidence.categories[evidenceType].push(file);
1385
+ evidence.total++;
1386
+ }
1387
+ }
1388
+ }
1389
+
1390
+ // Only read content if there are content patterns to check
1391
+ if (contentPatterns.length > 0) {
1392
+ let content;
1393
+ try {
1394
+ const fullPath = path.isAbsolute(file) ? file : path.join(repoPath, file);
1395
+ content = fs.readFileSync(fullPath, 'utf8');
1396
+ } catch {
1397
+ continue; // Skip unreadable files
1398
+ }
1399
+
1400
+ for (const { evidenceType, regex } of contentPatterns) {
1401
+ if (regex.test(content)) {
1402
+ if (!evidence.categories[evidenceType]) {
1403
+ evidence.categories[evidenceType] = [];
1404
+ }
1405
+ if (!evidence.categories[evidenceType].includes(file)) {
1406
+ evidence.categories[evidenceType].push(file);
1407
+ evidence.total++;
1408
+ }
1409
+ }
1410
+ }
1411
+ }
1412
+ }
1413
+
1414
+ evidence.found = Object.keys(evidence.categories);
1415
+ return evidence;
1416
+ }
1417
+
1418
+ /**
1419
+ * Detect gaps between claims and evidence
1420
+ *
1421
+ * @param {Array<Object>} claims - Extracted claims
1422
+ * @param {string} repoPath - Repository root path
1423
+ * @param {Object} evidencePatterns - Evidence patterns
1424
+ * @param {number} minEvidenceMatches - Minimum evidence required
1425
+ * @param {Array<string>} filesToSearch - Files to search for evidence
1426
+ * @param {Object} options - Options
1427
+ * @returns {Array<Object>} Violations
1428
+ */
1429
+ function detectGaps(claims, repoPath, evidencePatterns, minEvidenceMatches, filesToSearch, options = {}) {
1430
+ const violations = [];
1431
+
1432
+ // Cache evidence searches per category (avoid re-searching)
1433
+ const evidenceCache = new Map();
1434
+
1435
+ for (const claim of claims) {
1436
+ // Skip non-positive claims (TODOs, aspirational)
1437
+ if (!claim.isPositiveClaim) continue;
1438
+
1439
+ // Check cache first
1440
+ let evidence = evidenceCache.get(claim.category);
1441
+ if (!evidence) {
1442
+ evidence = searchEvidence(
1443
+ repoPath,
1444
+ claim.category,
1445
+ evidencePatterns,
1446
+ filesToSearch,
1447
+ options
1448
+ );
1449
+ evidenceCache.set(claim.category, evidence);
1450
+ }
1451
+
1452
+ // Check if sufficient evidence exists
1453
+ if (evidence.total < minEvidenceMatches) {
1454
+ violations.push({
1455
+ type: 'buzzword_inflation',
1456
+ file: claim.filePath,
1457
+ line: claim.line,
1458
+ buzzword: claim.buzzword,
1459
+ category: claim.category,
1460
+ claim: claim.text,
1461
+ evidenceFound: evidence.found,
1462
+ evidenceCount: evidence.total,
1463
+ evidenceRequired: minEvidenceMatches,
1464
+ severity: evidence.total === 0 ? 'high' : 'medium',
1465
+ message: `Claim "${claim.buzzword}" without sufficient evidence (found ${evidence.total}/${minEvidenceMatches} required)`
1466
+ });
1467
+ }
1468
+ }
1469
+
1470
+ return violations;
1471
+ }
1472
+
1473
+ /**
1474
+ * Analyze buzzword inflation - quality claims without supporting code evidence
1475
+ *
1476
+ * Detects claims like "production-ready", "secure", "scalable" in documentation
1477
+ * and comments, then searches for supporting evidence in the codebase.
1478
+ * Flags claims that lack sufficient evidence.
1479
+ *
1480
+ * @param {string} repoPath - Repository root path
1481
+ * @param {Object} options - Analysis options
1482
+ * @param {Object} [options.buzzwordCategories] - Buzzword category mappings
1483
+ * @param {Object} [options.evidencePatterns] - Evidence patterns per category
1484
+ * @param {number} [options.minEvidenceMatches=2] - Minimum evidence matches required
1485
+ * @returns {Object} Analysis results with violations
1486
+ */
1487
+ function analyzeBuzzwordInflation(repoPath, options = {}) {
1488
+ const fs = options.fs || require('fs');
1489
+ const path = options.path || require('path');
1490
+
1491
+ const buzzwordCategories = options.buzzwordCategories || BUZZWORD_CATEGORIES;
1492
+ const evidencePatterns = options.evidencePatterns || EVIDENCE_PATTERNS;
1493
+ const minEvidenceMatches = options.minEvidenceMatches || 2;
1494
+
1495
+ // Find files that may contain claims
1496
+ const claimSourceFiles = findClaimSourceFiles(repoPath, options);
1497
+
1498
+ // Find all source files for evidence searching (include tests - they're evidence)
1499
+ const { files: sourceFiles } = countSourceFiles(repoPath, { ...options, includeTests: true });
1500
+
1501
+ // Extract all claims from claim source files
1502
+ const allClaims = [];
1503
+ for (const file of claimSourceFiles) {
1504
+ let content;
1505
+ try {
1506
+ content = fs.readFileSync(path.join(repoPath, file), 'utf8');
1507
+ } catch {
1508
+ continue; // Skip unreadable files
1509
+ }
1510
+
1511
+ const claims = extractClaims(content, file, buzzwordCategories);
1512
+ allClaims.push(...claims);
1513
+ }
1514
+
1515
+ // Detect gaps (claims without evidence)
1516
+ const violations = detectGaps(
1517
+ allClaims,
1518
+ repoPath,
1519
+ evidencePatterns,
1520
+ minEvidenceMatches,
1521
+ sourceFiles,
1522
+ options
1523
+ );
1524
+
1525
+ return {
1526
+ claimsFound: allClaims.length,
1527
+ positiveClaimsFound: allClaims.filter(c => c.isPositiveClaim).length,
1528
+ violations,
1529
+ verdict: violations.length > 0
1530
+ ? (violations.some(v => v.severity === 'high') ? 'HIGH' : 'MEDIUM')
1531
+ : 'OK'
1532
+ };
1533
+ }
1534
+
1535
+ /**
1536
+ * Analyze infrastructure without implementation - setup without usage
1537
+ *
1538
+ * Detects infrastructure components (clients, connections, pools, services) that are
1539
+ * instantiated/configured but never actually used anywhere in the codebase.
1540
+ * This pattern often indicates dead code or incomplete implementations.
1541
+ *
1542
+ * @param {string} rootPath - Repository root path
1543
+ * @param {Object} options - Analysis options
1544
+ * @param {Array} [options.infrastructureSuffixes] - Component suffixes to detect
1545
+ * @param {Array} [options.setupVerbs] - Setup verbs to detect
1546
+ * @param {Object} [options.instantiationPatterns] - Language-specific patterns
1547
+ * @returns {Object} Analysis results: { setupsFound, usagesFound, violations, verdict }
1548
+ */
1549
+ function analyzeInfrastructureWithoutImplementation(rootPath, options = {}) {
1550
+ const fs = options.fs || require('fs');
1551
+ const path = options.path || require('path');
1552
+
1553
+ const instantiationPatterns = options.instantiationPatterns || INSTANTIATION_PATTERNS;
1554
+
1555
+ // Collect all source files (excluding tests by default)
1556
+ const { files: sourceFiles } = countSourceFiles(rootPath, {
1557
+ ...options,
1558
+ includeTests: false,
1559
+ maxFiles: 1000
1560
+ });
1561
+
1562
+ // Track infrastructure setups and their usage
1563
+ const infrastructureSetups = new Map(); // varName -> { file, line, type, component }
1564
+ const infrastructureUsage = new Map(); // varName -> { count, files[] }
1565
+
1566
+ // Cache file contents to avoid O(N*M) file reads
1567
+ // Phase 1 reads N files, Phase 2 would read N*M without caching
1568
+ const fileContentCache = new Map(); // file -> { content, lines }
1569
+
1570
+ // Phase 1: Find all infrastructure setups (single pass through files)
1571
+ for (const file of sourceFiles) {
1572
+ if (shouldExclude(file) || isTestFile(file)) continue;
1573
+
1574
+ let content;
1575
+ try {
1576
+ content = fs.readFileSync(path.join(rootPath, file), 'utf8');
1577
+ } catch (err) {
1578
+ // Skip unreadable files (permissions, binary, etc.)
1579
+ // This is expected for some files in the repository
1580
+ continue;
1581
+ }
1582
+
1583
+ // Cache content for Phase 2 usage search
1584
+ fileContentCache.set(file, { content, lines: content.split('\n') });
1585
+
1586
+ const lang = detectLanguage(file);
1587
+ const patterns = instantiationPatterns[lang] || instantiationPatterns.js;
1588
+
1589
+ for (const pattern of patterns) {
1590
+ // Reset regex state
1591
+ const regex = new RegExp(pattern.source, pattern.flags);
1592
+ let match;
1593
+ let matchCount = 0;
1594
+ const MAX_MATCHES_PER_FILE = 100; // Safety limit to prevent DoS
1595
+
1596
+ while ((match = regex.exec(content)) !== null && matchCount < MAX_MATCHES_PER_FILE) {
1597
+ matchCount++;
1598
+ const varName = match[1];
1599
+ const componentType = match[2] || 'Infrastructure';
1600
+
1601
+ // Skip if variable name is too generic (e.g., 'x', 'i', 'tmp')
1602
+ if (varName.length < 2 || GENERIC_VAR_PATTERN.test(varName)) continue;
1603
+
1604
+ const lineNumber = countNewlines(content.substring(0, match.index)) + 1;
1605
+
1606
+ // Store the setup location
1607
+ const key = `${file}:${varName}`;
1608
+ infrastructureSetups.set(key, {
1609
+ file,
1610
+ line: lineNumber,
1611
+ varName,
1612
+ type: componentType,
1613
+ content: content.split('\n')[lineNumber - 1].trim()
1614
+ });
1615
+
1616
+ // Initialize usage tracking
1617
+ if (!infrastructureUsage.has(key)) {
1618
+ infrastructureUsage.set(key, { count: 0, files: [] });
1619
+ }
1620
+ }
1621
+ }
1622
+ }
1623
+
1624
+ // Phase 2: Search for usage of each setup variable (using cached content)
1625
+ for (const [key, setup] of infrastructureSetups.entries()) {
1626
+ const { varName, file: setupFile } = setup;
1627
+
1628
+ // Pre-compile usage patterns once per variable for performance
1629
+ const escapedVarName = escapeRegex(varName);
1630
+ const usagePatterns = [
1631
+ new RegExp(`\\b${escapedVarName}\\s*\\.\\w+`), // varName.method()
1632
+ new RegExp(`\\b${escapedVarName}\\s*\\[`), // varName[prop]
1633
+ new RegExp(`\\(.*\\b${escapedVarName}\\b.*\\)`), // func(varName)
1634
+ new RegExp(`\\b${escapedVarName}\\s*\\)`), // func(arg, varName)
1635
+ new RegExp(`return\\s+.*\\b${escapedVarName}\\b`) // return varName
1636
+ ];
1637
+
1638
+ // Search for usage in all source files (using cache - O(N) instead of O(N*M))
1639
+ for (const [file, cached] of fileContentCache.entries()) {
1640
+ const { lines } = cached;
1641
+
1642
+ for (let i = 0; i < lines.length; i++) {
1643
+ const line = lines[i];
1644
+
1645
+ // Skip the setup line itself
1646
+ if (file === setupFile && i === setup.line - 1) continue;
1647
+
1648
+ // Look for usage patterns (method calls, property access, passed as argument)
1649
+ // Using word boundaries to avoid false positives
1650
+ for (const pattern of usagePatterns) {
1651
+ if (pattern.test(line)) {
1652
+ const usage = infrastructureUsage.get(key);
1653
+ usage.count++;
1654
+ if (!usage.files.includes(file)) {
1655
+ usage.files.push(file);
1656
+ }
1657
+ break; // Count once per line
1658
+ }
1659
+ }
1660
+ }
1661
+ }
1662
+ }
1663
+
1664
+ // Clear cache to free memory
1665
+ fileContentCache.clear();
1666
+
1667
+ // Phase 3: Detect violations (setups without usage)
1668
+ const violations = [];
1669
+ for (const [key, setup] of infrastructureSetups.entries()) {
1670
+ const usage = infrastructureUsage.get(key);
1671
+
1672
+ if (usage.count === 0) {
1673
+ // Check for false positives - might be exported or used in a way we didn't detect
1674
+ const setupContent = setup.content.toLowerCase();
1675
+
1676
+ // Skip if it's likely exported or part of a module.exports
1677
+ if (setupContent.includes('export') || setupContent.includes('module.exports')) {
1678
+ continue;
1679
+ }
1680
+
1681
+ // Skip if it's a parameter or destructured assignment
1682
+ if (setupContent.includes('function') && setupContent.includes(setup.varName)) {
1683
+ continue;
1684
+ }
1685
+
1686
+ violations.push({
1687
+ file: setup.file,
1688
+ line: setup.line,
1689
+ varName: setup.varName,
1690
+ type: setup.type,
1691
+ content: setup.content,
1692
+ severity: 'high',
1693
+ message: `Infrastructure component "${setup.varName}" (${setup.type}) is created but never used`
1694
+ });
1695
+ }
1696
+ }
1697
+
1698
+ return {
1699
+ setupsFound: infrastructureSetups.size,
1700
+ usagesFound: Array.from(infrastructureUsage.values()).filter(u => u.count > 0).length,
1701
+ violations,
1702
+ verdict: violations.length > 0 ? 'HIGH' : 'OK'
1703
+ };
1704
+ }
1705
+
1706
+ // ============================================================================
1707
+ // Dead Code Detection
1708
+ // Detects unreachable code after return/throw/break/continue statements
1709
+ // ============================================================================
1710
+
1711
+ /**
1712
+ * Language-specific control flow termination patterns
1713
+ * These statements terminate the current execution path
1714
+ */
1715
+ const TERMINATION_STATEMENTS = {
1716
+ js: [
1717
+ /\breturn\s*(?:[^;]*)?;/,
1718
+ /\bthrow\s+/,
1719
+ /\bbreak\s*;/,
1720
+ /\bcontinue\s*;/
1721
+ ],
1722
+ python: [
1723
+ /^\s*return(?:\s+|$)/m,
1724
+ /^\s*raise\s+/m,
1725
+ /^\s*break\s*$/m,
1726
+ /^\s*continue\s*$/m
1727
+ ],
1728
+ go: [
1729
+ /\breturn\b/,
1730
+ /\bpanic\s*\(/,
1731
+ /\bbreak\s*$/m,
1732
+ /\bcontinue\s*$/m
1733
+ ],
1734
+ rust: [
1735
+ /\breturn\s*(?:[^;]*)?;/,
1736
+ /\bpanic!\s*\(/,
1737
+ /\bbreak\s*;/,
1738
+ /\bcontinue\s*;/
1739
+ ],
1740
+ java: [
1741
+ /\breturn\s*(?:[^;]*)?;/,
1742
+ /\bthrow\s+/,
1743
+ /\bbreak\s*;/,
1744
+ /\bcontinue\s*;/
1745
+ ]
1746
+ };
1747
+
1748
+ /**
1749
+ * Patterns for block start (opening braces/colons)
1750
+ */
1751
+ const BLOCK_START_PATTERNS = {
1752
+ js: /\{[\s]*$/,
1753
+ python: /:[\s]*$/,
1754
+ go: /\{[\s]*$/,
1755
+ rust: /\{[\s]*$/
1756
+ };
1757
+
1758
+ /**
1759
+ * Analyze dead code - unreachable statements after control flow terminators
1760
+ *
1761
+ * Detects code that appears after return, throw, break, or continue statements
1762
+ * within the same block scope. This is a common sign of incomplete refactoring
1763
+ * or copy-paste errors.
1764
+ *
1765
+ * @param {string} content - File content to analyze
1766
+ * @param {Object} options - Analysis options
1767
+ * @param {string} [options.filePath] - File path for language detection
1768
+ * @returns {Array<Object>} Array of violations: { line, terminatedBy, deadCode }
1769
+ */
1770
+ function analyzeDeadCode(content, options = {}) {
1771
+ const lang = detectLanguage(options.filePath || '.js');
1772
+ const violations = [];
1773
+ const terminationPatterns = TERMINATION_STATEMENTS[lang] || TERMINATION_STATEMENTS.js;
1774
+
1775
+ const lines = content.split('\n');
1776
+ const lineCount = lines.length;
1777
+
1778
+ for (let i = 0; i < lineCount; i++) {
1779
+ const line = lines[i];
1780
+ const trimmed = line.trim();
1781
+
1782
+ // Skip empty lines, comments, and closing braces
1783
+ if (!trimmed || trimmed.startsWith('//') || trimmed.startsWith('#') ||
1784
+ trimmed.startsWith('/*') || trimmed.startsWith('*') ||
1785
+ trimmed === '}' || trimmed === '},' || trimmed === '};') {
1786
+ continue;
1787
+ }
1788
+
1789
+ // Check if this line contains a termination statement
1790
+ let isTermination = false;
1791
+ let terminationType = '';
1792
+
1793
+ for (const pattern of terminationPatterns) {
1794
+ if (pattern.test(trimmed)) {
1795
+ isTermination = true;
1796
+ terminationType = trimmed.match(/\b(return|throw|break|continue|panic|raise)\b/i)?.[1] || 'terminator';
1797
+ break;
1798
+ }
1799
+ }
1800
+
1801
+ if (!isTermination) continue;
1802
+
1803
+ // Skip if termination is part of a one-line conditional (e.g., "if (x) return;")
1804
+ // These don't make subsequent code unreachable
1805
+ if (/^\s*(if|elif|else\s+if)\s*\(/.test(trimmed) ||
1806
+ /^[ \t]*if\s[^:\n]*:/.test(trimmed)) {
1807
+ continue;
1808
+ }
1809
+
1810
+ // Check for multi-line statements (unbalanced brackets)
1811
+ // e.g., "throw new Error(" or "return [" continues on next lines
1812
+ const countBrackets = (str) => {
1813
+ const open = (str.match(/[\(\[\{]/g) || []).length;
1814
+ const close = (str.match(/[\)\]\}]/g) || []).length;
1815
+ return open - close;
1816
+ };
1817
+ let bracketBalance = countBrackets(trimmed);
1818
+ if (bracketBalance > 0) {
1819
+ // Statement continues on following lines - skip to where it ends
1820
+ for (let k = i + 1; k < lineCount && bracketBalance > 0; k++) {
1821
+ const contLine = lines[k].trim();
1822
+ bracketBalance += countBrackets(contLine);
1823
+ i = k; // Advance past continuation lines
1824
+ }
1825
+ }
1826
+
1827
+ // Look for non-empty code after the termination (within same block)
1828
+ // Use different scope tracking for Python vs brace-based languages
1829
+ const isPython = lang === 'python';
1830
+ const currentIndent = isPython ? (line.match(/^\s*/)[0].length) : null;
1831
+ let braceDepth = 0;
1832
+
1833
+ for (let j = i + 1; j < lineCount; j++) {
1834
+ const nextLine = lines[j];
1835
+ const nextTrimmed = nextLine.trim();
1836
+
1837
+ // Skip empty lines and comments
1838
+ if (!nextTrimmed || nextTrimmed.startsWith('//') || nextTrimmed.startsWith('#') ||
1839
+ nextTrimmed.startsWith('/*') || nextTrimmed.startsWith('*')) {
1840
+ continue;
1841
+ }
1842
+
1843
+ // Python: Check indentation level to detect scope exit
1844
+ if (isPython) {
1845
+ const nextIndent = nextLine.match(/^\s*/)[0].length;
1846
+
1847
+ // If dedented to LESS than current level, we've exited the block
1848
+ if (nextIndent < currentIndent) {
1849
+ break;
1850
+ }
1851
+ } else {
1852
+ // Brace-based languages: Track brace depth
1853
+ const openBraces = (nextTrimmed.match(/\{/g) || []).length;
1854
+ const closeBraces = (nextTrimmed.match(/\}/g) || []).length;
1855
+ braceDepth += openBraces - closeBraces;
1856
+
1857
+ // If we see a closing brace that takes us out of the current scope, stop
1858
+ if (braceDepth < 0) break;
1859
+
1860
+ // If we see only a closing brace, that's fine (not dead code)
1861
+ if (nextTrimmed === '}' || nextTrimmed === '},' || nextTrimmed === '};') {
1862
+ continue;
1863
+ }
1864
+ }
1865
+
1866
+ // Skip case/default labels in switch statements
1867
+ if (/^(case\s+|default\s*:)/.test(nextTrimmed)) {
1868
+ break;
1869
+ }
1870
+
1871
+ // Skip else/elif/except/catch clauses (they're alternative paths, not dead code)
1872
+ // Handles: "} else {", "} catch {", "} catch (e) {", "catch {" (modern JS without binding)
1873
+ if (/^(else\s*[:{]?|elif\s+|else\s+if\s+|except\s*[:(]|catch\s*[({]|\}\s*else\s*|\}\s*catch\s*)/.test(nextTrimmed)) {
1874
+ break;
1875
+ }
1876
+
1877
+ // Found potential dead code
1878
+ violations.push({
1879
+ line: j + 1, // 1-indexed
1880
+ terminationType: terminationType,
1881
+ terminationLine: i + 1,
1882
+ content: nextTrimmed.substring(0, 50) + (nextTrimmed.length > 50 ? '...' : ''),
1883
+ severity: 'high'
1884
+ });
1885
+
1886
+ // Only report the first dead line per terminator (avoids noise)
1887
+ break;
1888
+ }
1889
+ }
1890
+
1891
+ return violations;
1892
+ }
1893
+
1894
+ // ============================================================================
1895
+ // Shotgun Surgery Detection
1896
+ // Detects files that frequently change together across commits
1897
+ // ============================================================================
1898
+
1899
+ /**
1900
+ * Analyze shotgun surgery - files that frequently change together
1901
+ *
1902
+ * Uses git log to find commits where multiple files change together,
1903
+ * indicating tight coupling that may need refactoring.
1904
+ *
1905
+ * @param {string} repoPath - Repository root path
1906
+ * @param {Object} options - Analysis options
1907
+ * @param {number} [options.commitLimit=100] - Number of commits to analyze
1908
+ * @param {number} [options.clusterThreshold=5] - Min files changed together to flag
1909
+ * @param {Function} [options.execFileSync] - Command executor (for testing)
1910
+ * @returns {Object} Analysis results: { clusters, violations, verdict }
1911
+ */
1912
+ function analyzeShotgunSurgery(repoPath, options = {}) {
1913
+ // Validate commitLimit to prevent command injection
1914
+ let commitLimit = parseInt(options.commitLimit, 10) || 100;
1915
+ if (!Number.isInteger(commitLimit) || commitLimit < 1 || commitLimit > 10000) {
1916
+ commitLimit = 100;
1917
+ }
1918
+ const clusterThreshold = options.clusterThreshold || 5;
1919
+ const execFileSync = options.execFileSync || require('child_process').execFileSync;
1920
+ const path = options.path || require('path');
1921
+
1922
+ const violations = [];
1923
+ const fileClusters = new Map(); // "file1,file2" -> count
1924
+
1925
+ try {
1926
+ // Get commit hashes with file changes
1927
+ // maxBuffer: 2MB is sufficient for 100 commits (typical output is ~50-200KB)
1928
+ const logResult = execFileSync(
1929
+ 'git',
1930
+ ['log', '--name-only', '--pretty=format:COMMIT:%H', '-n', String(commitLimit)],
1931
+ { cwd: repoPath, encoding: 'utf8', maxBuffer: 2 * 1024 * 1024 }
1932
+ );
1933
+
1934
+ // Parse commits and their files
1935
+ const commits = [];
1936
+ let currentCommit = null;
1937
+
1938
+ for (const line of logResult.split('\n')) {
1939
+ const trimmed = line.trim();
1940
+ if (!trimmed) continue;
1941
+
1942
+ if (trimmed.startsWith('COMMIT:')) {
1943
+ if (currentCommit && currentCommit.files.length > 1) {
1944
+ commits.push(currentCommit);
1945
+ }
1946
+ currentCommit = { hash: trimmed.substring(7), files: [] };
1947
+ } else if (currentCommit) {
1948
+ // Filter to source files only, exclude common uninteresting files
1949
+ const ext = path.extname(trimmed);
1950
+ if (['.js', '.ts', '.jsx', '.tsx', '.py', '.go', '.rs', '.java'].includes(ext)) {
1951
+ // Skip test files, they often change with implementation
1952
+ if (!isTestFile(trimmed) && !shouldExclude(trimmed)) {
1953
+ currentCommit.files.push(trimmed);
1954
+ }
1955
+ }
1956
+ }
1957
+ }
1958
+
1959
+ // Don't forget the last commit
1960
+ if (currentCommit && currentCommit.files.length > 1) {
1961
+ commits.push(currentCommit);
1962
+ }
1963
+
1964
+ // Build co-change matrix
1965
+ for (const commit of commits) {
1966
+ const files = commit.files;
1967
+ if (files.length < 2 || files.length > 20) continue; // Skip huge commits
1968
+
1969
+ // Count co-changes for each pair
1970
+ for (let i = 0; i < files.length; i++) {
1971
+ for (let j = i + 1; j < files.length; j++) {
1972
+ const pair = [files[i], files[j]].sort().join('|||');
1973
+ fileClusters.set(pair, (fileClusters.get(pair) || 0) + 1);
1974
+ }
1975
+ }
1976
+ }
1977
+
1978
+ // Find highly coupled file pairs (appear together in 3+ commits)
1979
+ const coupledPairs = [];
1980
+ for (const [pair, count] of fileClusters.entries()) {
1981
+ if (count >= 3) {
1982
+ const [file1, file2] = pair.split('|||');
1983
+ coupledPairs.push({ file1, file2, count });
1984
+ }
1985
+ }
1986
+
1987
+ // Sort by frequency
1988
+ coupledPairs.sort((a, b) => b.count - a.count);
1989
+
1990
+ // Find clusters of files that frequently change together
1991
+ // A cluster is when a file appears in multiple coupled pairs
1992
+ const fileFrequency = new Map(); // file -> number of coupled pairs it appears in
1993
+ for (const { file1, file2 } of coupledPairs) {
1994
+ fileFrequency.set(file1, (fileFrequency.get(file1) || 0) + 1);
1995
+ fileFrequency.set(file2, (fileFrequency.get(file2) || 0) + 1);
1996
+ }
1997
+
1998
+ // Files that appear in many coupled pairs indicate shotgun surgery
1999
+ const frequentlyChangedFiles = Array.from(fileFrequency.entries())
2000
+ .filter(([_, count]) => count >= clusterThreshold)
2001
+ .sort((a, b) => b[1] - a[1]);
2002
+
2003
+ // Report violations
2004
+ for (const [file, coupledCount] of frequentlyChangedFiles) {
2005
+ // Find all files this one is coupled with
2006
+ const coupledWith = coupledPairs
2007
+ .filter(p => p.file1 === file || p.file2 === file)
2008
+ .map(p => p.file1 === file ? p.file2 : p.file1)
2009
+ .slice(0, 5); // Limit to top 5 for readability
2010
+
2011
+ violations.push({
2012
+ file,
2013
+ coupledCount,
2014
+ coupledWith,
2015
+ severity: coupledCount >= clusterThreshold * 2 ? 'high' : 'medium',
2016
+ message: `"${file}" changes with ${coupledCount} other files frequently (shotgun surgery indicator)`
2017
+ });
2018
+ }
2019
+
2020
+ return {
2021
+ commitsAnalyzed: commits.length,
2022
+ coupledPairs: coupledPairs.slice(0, 20), // Top 20 for report
2023
+ violations,
2024
+ verdict: violations.length > 0
2025
+ ? (violations.some(v => v.severity === 'high') ? 'HIGH' : 'MEDIUM')
2026
+ : 'OK'
2027
+ };
2028
+
2029
+ } catch (err) {
2030
+ // Git command failed - likely not a git repo or no commits
2031
+ return {
2032
+ commitsAnalyzed: 0,
2033
+ coupledPairs: [],
2034
+ violations: [],
2035
+ verdict: 'SKIP',
2036
+ error: err.message
2037
+ };
2038
+ }
2039
+ }
2040
+
2041
+ // ============================================================================
2042
+ // Stub Function Detection
2043
+ // Detects functions that only return placeholder values without real logic
2044
+ // ============================================================================
2045
+
2046
+ /**
2047
+ * Analyze stub functions - functions that only return placeholder values
2048
+ *
2049
+ * A stub function is one where:
2050
+ * - The body contains only a return statement (plus optional comments)
2051
+ * - The return value is a placeholder: 0, null, undefined, true, false, [], {}, "", ''
2052
+ *
2053
+ * Higher certainty when TODO/FIXME comments are present.
2054
+ *
2055
+ * @param {string} content - File content to analyze
2056
+ * @param {Object} options - Analysis options
2057
+ * @param {string} [options.filePath] - File path for language detection
2058
+ * @returns {Array<Object>} Array of violations: { line, functionName, returnValue, hasTodo, certainty }
2059
+ */
2060
+ function analyzeStubFunctions(content, options = {}) {
2061
+ const violations = [];
2062
+ const lang = detectLanguage(options.filePath || '.js');
2063
+
2064
+ const langConfig = getStubFunctionConfig(lang);
2065
+ if (!langConfig) return violations;
2066
+
2067
+ if (langConfig.useBraces) {
2068
+ return analyzeStubFunctionsBraceLanguage(content, lang, langConfig);
2069
+ } else {
2070
+ return analyzeStubFunctionsPython(content);
2071
+ }
2072
+ }
2073
+
2074
+ /**
2075
+ * Get language-specific configuration for stub detection
2076
+ */
2077
+ function getStubFunctionConfig(lang) {
2078
+ const configs = {
2079
+ js: {
2080
+ useBraces: true,
2081
+ functionPatterns: [
2082
+ /(?:async\s+)?function\s+(\w+)\s*\([^)]*\)\s*\{/g,
2083
+ /(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s*)?\([^)]*\)\s*=>\s*\{/g,
2084
+ /(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?function\s*\([^)]*\)\s*\{/g,
2085
+ /^\s*(?:async\s+)?(?!if\b|for\b|while\b|switch\b|catch\b|with\b|function\b)(\w+)\s*\([^)]*\)\s*\{/gm,
2086
+ ],
2087
+ stubReturnPattern: /^\s*return\s+(0|null|undefined|true|false|\[\]|\{\}|""|''|``)\s*;?\s*$/,
2088
+ commentPatterns: [/^\s*\/\//, /^\s*\/\*/, /^\s*\*/, /^\s*\*\/$/],
2089
+ },
2090
+ rust: {
2091
+ useBraces: true,
2092
+ functionPatterns: [
2093
+ /(?:pub\s+)?(?:async\s+)?fn\s+(\w+)\s*(?:<[^>]*>)?\s*\([^)]*\)(?:\s*->\s*[^{]+)?\s*\{/g,
2094
+ ],
2095
+ stubReturnPattern: /^\s*(?:return\s+)?(None|0|true|false|String::new\(\)|Vec::new\(\)|vec!\[\]|\(\)|""|Default::default\(\))\s*;?\s*$/,
2096
+ stubMacroPattern: /^\s*(todo!\(\)|unimplemented!\(\)|panic!\([^)]*\))\s*;?\s*$/,
2097
+ commentPatterns: [/^\s*\/\//, /^\s*\/\*/, /^\s*\*/, /^\s*\*\/$/],
2098
+ },
2099
+ java: {
2100
+ useBraces: true,
2101
+ functionPatterns: [
2102
+ /(?:public|private|protected)?\s*(?:static\s+)?(?:final\s+)?(?:\w+(?:<[^>]*>)?)\s+(\w+)\s*\([^)]*\)\s*(?:throws\s+[^{]+)?\s*\{/g,
2103
+ ],
2104
+ stubReturnPattern: /^\s*return\s+(null|0|0L|0\.0|0\.0f|true|false|""|Collections\.emptyList\(\)|Collections\.emptyMap\(\)|Optional\.empty\(\))\s*;\s*$/,
2105
+ throwStubPattern: /^\s*throw\s+new\s+(?:Unsupported(?:Operation)?Exception|NotImplementedException|IllegalStateException)\s*\([^)]*\)\s*;\s*$/,
2106
+ commentPatterns: [/^\s*\/\//, /^\s*\/\*/, /^\s*\*/, /^\s*\*\/$/],
2107
+ },
2108
+ go: {
2109
+ useBraces: true,
2110
+ functionPatterns: [
2111
+ /func\s+(?:\([^)]+\)\s+)?(\w+)\s*\([^)]*\)(?:\s*(?:\([^)]+\)|[^{]+))?\s*\{/g,
2112
+ ],
2113
+ stubReturnPattern: /^\s*return\s+(nil|0|""|false|true|\[\][a-zA-Z_]\w*\{\}|map\[[^\]]+\][a-zA-Z_]\w*\{\}|\&?[A-Z]\w*\{\})\s*$/,
2114
+ panicPattern: /^\s*panic\s*\([^)]*\)\s*$/,
2115
+ commentPatterns: [/^\s*\/\//],
2116
+ },
2117
+ python: {
2118
+ useBraces: false,
2119
+ },
2120
+ };
2121
+
2122
+ return configs[lang];
2123
+ }
2124
+
2125
+ /**
2126
+ * Analyze brace-delimited languages (JS, Rust, Java, Go)
2127
+ */
2128
+ function analyzeStubFunctionsBraceLanguage(content, lang, config) {
2129
+ const violations = [];
2130
+
2131
+ for (const pattern of config.functionPatterns) {
2132
+ let match;
2133
+ pattern.lastIndex = 0;
2134
+
2135
+ while ((match = pattern.exec(content)) !== null) {
2136
+ const funcName = match[1] || 'anonymous';
2137
+ const funcStart = match.index + match[0].length - 1;
2138
+
2139
+ const closingBrace = findMatchingBrace(content, funcStart);
2140
+ if (closingBrace === -1) continue;
2141
+
2142
+ const bodyContent = content.substring(funcStart + 1, closingBrace);
2143
+ const bodyLines = bodyContent.split('\n');
2144
+
2145
+ const significantLines = bodyLines.filter(line => {
2146
+ const trimmed = line.trim();
2147
+ if (!trimmed) return false;
2148
+ for (const commentPattern of config.commentPatterns) {
2149
+ if (commentPattern.test(trimmed)) return false;
2150
+ }
2151
+ return true;
2152
+ });
2153
+
2154
+ if (significantLines.length === 1) {
2155
+ const onlyLine = significantLines[0].trim();
2156
+ let stubMatch = config.stubReturnPattern.exec(onlyLine);
2157
+ let returnValue = stubMatch ? stubMatch[1] : null;
2158
+
2159
+ if (!stubMatch && config.stubMacroPattern) {
2160
+ stubMatch = config.stubMacroPattern.exec(onlyLine);
2161
+ returnValue = stubMatch ? stubMatch[1] : null;
2162
+ }
2163
+ if (!stubMatch && config.throwStubPattern) {
2164
+ stubMatch = config.throwStubPattern.exec(onlyLine);
2165
+ returnValue = stubMatch ? 'throw stub' : null;
2166
+ }
2167
+ if (!stubMatch && config.panicPattern) {
2168
+ stubMatch = config.panicPattern.exec(onlyLine);
2169
+ returnValue = stubMatch ? 'panic' : null;
2170
+ }
2171
+
2172
+ if (stubMatch && returnValue) {
2173
+ const hasTodo = /\b(TODO|FIXME|XXX|HACK|STUB)\b/i.test(bodyContent);
2174
+ const lineNumber = countNewlines(content.substring(0, funcStart)) + 1;
2175
+
2176
+ violations.push({
2177
+ line: lineNumber,
2178
+ functionName: funcName,
2179
+ returnValue: returnValue,
2180
+ hasTodo: hasTodo,
2181
+ certainty: hasTodo ? 'HIGH' : 'MEDIUM',
2182
+ content: `${funcName}() returns ${returnValue}`
2183
+ });
2184
+ }
2185
+ }
2186
+ }
2187
+ }
2188
+
2189
+ return violations;
2190
+ }
2191
+
2192
+ /**
2193
+ * Analyze Python functions (indentation-based)
2194
+ */
2195
+ function analyzeStubFunctionsPython(content) {
2196
+ const violations = [];
2197
+ const lines = content.split('\n');
2198
+
2199
+ const defPattern = /^(\s*)(?:async\s+)?def\s+(\w+)\s*\([^)]*\)\s*(?:->.*)?:\s*$/;
2200
+ const stubReturns = [
2201
+ /^\s*return\s+(None|0|True|False|\[\]|\{\}|"")\s*$/,
2202
+ /^\s*pass\s*$/,
2203
+ /^\s*raise\s+NotImplementedError\s*\([^)]*\)\s*$/,
2204
+ /^\s*\.\.\.\s*$/,
2205
+ ];
2206
+ const commentPattern = /^\s*#/;
2207
+
2208
+ for (let i = 0; i < lines.length; i++) {
2209
+ const match = defPattern.exec(lines[i]);
2210
+ if (!match) continue;
2211
+
2212
+ const funcIndent = match[1].length;
2213
+ const funcName = match[2];
2214
+
2215
+ const bodyLines = [];
2216
+ for (let j = i + 1; j < lines.length; j++) {
2217
+ const line = lines[j];
2218
+ const trimmed = line.trim();
2219
+
2220
+ if (!trimmed) continue;
2221
+
2222
+ const lineIndent = line.length - line.trimStart().length;
2223
+ if (lineIndent <= funcIndent && trimmed) break;
2224
+
2225
+ if (!commentPattern.test(trimmed) && !trimmed.startsWith('"""') && !trimmed.startsWith("'''")) {
2226
+ bodyLines.push(trimmed);
2227
+ }
2228
+ }
2229
+
2230
+ if (bodyLines.length === 1) {
2231
+ const onlyLine = bodyLines[0];
2232
+ for (const stubPattern of stubReturns) {
2233
+ const stubMatch = stubPattern.exec(onlyLine);
2234
+ if (stubMatch) {
2235
+ const returnValue = stubMatch[1] || onlyLine.trim();
2236
+ const hasTodo = /\b(TODO|FIXME|XXX|HACK|STUB)\b/i.test(
2237
+ lines.slice(i, Math.min(i + 10, lines.length)).join('\n')
2238
+ );
2239
+
2240
+ violations.push({
2241
+ line: i + 1,
2242
+ functionName: funcName,
2243
+ returnValue: returnValue,
2244
+ hasTodo: hasTodo,
2245
+ certainty: hasTodo ? 'HIGH' : 'MEDIUM',
2246
+ content: `def ${funcName}(): ${onlyLine}`
2247
+ });
2248
+ break;
2249
+ }
2250
+ }
2251
+ }
2252
+ }
2253
+
2254
+ return violations;
2255
+ }
2256
+
2257
+ module.exports = {
2258
+ analyzeDocCodeRatio,
2259
+ analyzeVerbosityRatio,
2260
+ analyzeOverEngineering,
2261
+ analyzeBuzzwordInflation,
2262
+ analyzeInfrastructureWithoutImplementation,
2263
+ analyzeDeadCode,
2264
+ analyzeShotgunSurgery,
2265
+ analyzeStubFunctions,
2266
+ // Export helpers for testing
2267
+ findMatchingBrace,
2268
+ countNonEmptyLines,
2269
+ countSourceFiles,
2270
+ countSourceLines,
2271
+ countEntryPointExports,
2272
+ countExportsInContent,
2273
+ getMaxDirectoryDepth,
2274
+ detectLanguage,
2275
+ detectCommentLanguage,
2276
+ shouldExclude,
2277
+ isTestFile,
2278
+ parseGitignore,
2279
+ // Buzzword inflation helpers (for testing)
2280
+ extractClaims,
2281
+ searchEvidence,
2282
+ detectGaps,
2283
+ findClaimSourceFiles,
2284
+ escapeRegex,
2285
+ isFilePathPattern,
2286
+ // Export constants for testing
2287
+ ENTRY_POINTS,
2288
+ EXPORT_PATTERNS,
2289
+ SOURCE_EXTENSIONS,
2290
+ EXCLUDE_DIRS,
2291
+ COMMENT_SYNTAX,
2292
+ // Buzzword inflation constants
2293
+ BUZZWORD_CATEGORIES,
2294
+ EVIDENCE_PATTERNS,
2295
+ CLAIM_INDICATORS,
2296
+ NOT_CLAIM_INDICATORS,
2297
+ // Infrastructure detection constants
2298
+ INFRASTRUCTURE_SUFFIXES,
2299
+ SETUP_VERBS,
2300
+ INSTANTIATION_PATTERNS,
2301
+ GENERIC_VAR_PATTERN,
2302
+ // Dead code detection constants
2303
+ TERMINATION_STATEMENTS,
2304
+ BLOCK_START_PATTERNS
2305
+ };