@boyingliu01/xp-gate 0.8.1 → 0.8.4

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 (315) hide show
  1. package/adapters/java.sh +1 -1
  2. package/adapters/plugins/book299-20132-python/README.md +21 -0
  3. package/adapters/plugins/book299-20132-python/plugin.yml +21 -0
  4. package/adapters/plugins/book299-20132-python/rules/exception/gen-0023.yml +14 -0
  5. package/adapters/plugins/book299-20132-python/rules/logging/gen-0071.yml +14 -0
  6. package/adapters/plugins/book299-20132-python/rules/style/gen-0001.yml +14 -0
  7. package/adapters/plugins/book299-20132-python/rules/style/gen-0002.yml +14 -0
  8. package/adapters/plugins/book299-20132-python/rules/style/gen-0003.yml +14 -0
  9. package/adapters/plugins/book299-20132-python/rules/style/gen-0004.yml +14 -0
  10. package/adapters/plugins/book299-20132-python/rules/style/gen-0005.yml +14 -0
  11. package/adapters/plugins/book299-20132-python/rules/style/gen-0006.yml +14 -0
  12. package/adapters/plugins/book299-20132-python/rules/style/gen-0007.yml +14 -0
  13. package/adapters/plugins/book299-20132-python/rules/style/gen-0008.yml +14 -0
  14. package/adapters/plugins/book299-20132-python/rules/style/gen-0009.yml +14 -0
  15. package/adapters/plugins/book299-20132-python/rules/style/gen-0010.yml +14 -0
  16. package/adapters/plugins/book299-20132-python/rules/style/gen-0011.yml +14 -0
  17. package/adapters/plugins/book299-20132-python/rules/style/gen-0012.yml +14 -0
  18. package/adapters/plugins/book299-20132-python/rules/style/gen-0013.yml +14 -0
  19. package/adapters/plugins/book299-20132-python/rules/style/gen-0014.yml +14 -0
  20. package/adapters/plugins/book299-20132-python/rules/style/gen-0015.yml +14 -0
  21. package/adapters/plugins/book299-20132-python/rules/style/gen-0016.yml +14 -0
  22. package/adapters/plugins/book299-20132-python/rules/style/gen-0017.yml +14 -0
  23. package/adapters/plugins/book299-20132-python/rules/style/gen-0018.yml +14 -0
  24. package/adapters/plugins/book299-20132-python/rules/style/gen-0019.yml +14 -0
  25. package/adapters/plugins/book299-20132-python/rules/style/gen-0020.yml +14 -0
  26. package/adapters/plugins/book299-20132-python/rules/style/gen-0021.yml +14 -0
  27. package/adapters/plugins/book299-20132-python/rules/style/gen-0022.yml +14 -0
  28. package/adapters/plugins/book299-20132-python/rules/style/gen-0024.yml +14 -0
  29. package/adapters/plugins/book299-20132-python/rules/style/gen-0025.yml +14 -0
  30. package/adapters/plugins/book299-20132-python/rules/style/gen-0026.yml +14 -0
  31. package/adapters/plugins/book299-20132-python/rules/style/gen-0027.yml +14 -0
  32. package/adapters/plugins/book299-20132-python/rules/style/gen-0028.yml +14 -0
  33. package/adapters/plugins/book299-20132-python/rules/style/gen-0029.yml +14 -0
  34. package/adapters/plugins/book299-20132-python/rules/style/gen-0030.yml +14 -0
  35. package/adapters/plugins/book299-20132-python/rules/style/gen-0031.yml +14 -0
  36. package/adapters/plugins/book299-20132-python/rules/style/gen-0032.yml +14 -0
  37. package/adapters/plugins/book299-20132-python/rules/style/gen-0033.yml +14 -0
  38. package/adapters/plugins/book299-20132-python/rules/style/gen-0034.yml +14 -0
  39. package/adapters/plugins/book299-20132-python/rules/style/gen-0035.yml +14 -0
  40. package/adapters/plugins/book299-20132-python/rules/style/gen-0036.yml +14 -0
  41. package/adapters/plugins/book299-20132-python/rules/style/gen-0037.yml +14 -0
  42. package/adapters/plugins/book299-20132-python/rules/style/gen-0038.yml +14 -0
  43. package/adapters/plugins/book299-20132-python/rules/style/gen-0039.yml +14 -0
  44. package/adapters/plugins/book299-20132-python/rules/style/gen-0040.yml +14 -0
  45. package/adapters/plugins/book299-20132-python/rules/style/gen-0041.yml +14 -0
  46. package/adapters/plugins/book299-20132-python/rules/style/gen-0042.yml +14 -0
  47. package/adapters/plugins/book299-20132-python/rules/style/gen-0043.yml +14 -0
  48. package/adapters/plugins/book299-20132-python/rules/style/gen-0044.yml +14 -0
  49. package/adapters/plugins/book299-20132-python/rules/style/gen-0045.yml +14 -0
  50. package/adapters/plugins/book299-20132-python/rules/style/gen-0046.yml +14 -0
  51. package/adapters/plugins/book299-20132-python/rules/style/gen-0047.yml +14 -0
  52. package/adapters/plugins/book299-20132-python/rules/style/gen-0048.yml +14 -0
  53. package/adapters/plugins/book299-20132-python/rules/style/gen-0049.yml +14 -0
  54. package/adapters/plugins/book299-20132-python/rules/style/gen-0050.yml +14 -0
  55. package/adapters/plugins/book299-20132-python/rules/style/gen-0051.yml +14 -0
  56. package/adapters/plugins/book299-20132-python/rules/style/gen-0052.yml +14 -0
  57. package/adapters/plugins/book299-20132-python/rules/style/gen-0053.yml +14 -0
  58. package/adapters/plugins/book299-20132-python/rules/style/gen-0054.yml +14 -0
  59. package/adapters/plugins/book299-20132-python/rules/style/gen-0055.yml +14 -0
  60. package/adapters/plugins/book299-20132-python/rules/style/gen-0056.yml +14 -0
  61. package/adapters/plugins/book299-20132-python/rules/style/gen-0057.yml +14 -0
  62. package/adapters/plugins/book299-20132-python/rules/style/gen-0058.yml +14 -0
  63. package/adapters/plugins/book299-20132-python/rules/style/gen-0059.yml +14 -0
  64. package/adapters/plugins/book299-20132-python/rules/style/gen-0060.yml +14 -0
  65. package/adapters/plugins/book299-20132-python/rules/style/gen-0061.yml +14 -0
  66. package/adapters/plugins/book299-20132-python/rules/style/gen-0062.yml +14 -0
  67. package/adapters/plugins/book299-20132-python/rules/style/gen-0063.yml +14 -0
  68. package/adapters/plugins/book299-20132-python/rules/style/gen-0064.yml +14 -0
  69. package/adapters/plugins/book299-20132-python/rules/style/gen-0065.yml +14 -0
  70. package/adapters/plugins/book299-20132-python/rules/style/gen-0066.yml +14 -0
  71. package/adapters/plugins/book299-20132-python/rules/style/gen-0067.yml +14 -0
  72. package/adapters/plugins/book299-20132-python/rules/style/gen-0068.yml +14 -0
  73. package/adapters/plugins/book299-20132-python/rules/style/gen-0069.yml +14 -0
  74. package/adapters/plugins/book299-20132-python/rules/style/gen-0070.yml +14 -0
  75. package/adapters/plugins/book299-20132-python/rules/style/gen-0072.yml +14 -0
  76. package/adapters/plugins/book299-20132-python/rules/style/gen-0073.yml +14 -0
  77. package/adapters/plugins/book299-20132-python/scripts/install-gradle.sh +4 -0
  78. package/adapters/plugins/book299-20132-python/scripts/install-maven.sh +20 -0
  79. package/adapters/plugins/book299-4081-c/README.md +21 -0
  80. package/adapters/plugins/book299-4081-c/plugin.yml +21 -0
  81. package/adapters/plugins/book299-4081-c/rules/collection/c/345/273/272-5-12.yml +14 -0
  82. package/adapters/plugins/book299-4081-c/rules/collection/c/345/273/272-5-8.yml +14 -0
  83. package/adapters/plugins/book299-4081-c/rules/concurrency/c/350/247/204-4-19.yml +14 -0
  84. package/adapters/plugins/book299-4081-c/rules/concurrency/c/350/247/204-4-20.yml +14 -0
  85. package/adapters/plugins/book299-4081-c/rules/exception/c/350/247/204-4-11.yml +14 -0
  86. package/adapters/plugins/book299-4081-c/rules/exception/c/350/247/204-4-12.yml +14 -0
  87. package/adapters/plugins/book299-4081-c/rules/exception/c/350/247/204-4-6.yml +14 -0
  88. package/adapters/plugins/book299-4081-c/rules/exception/c/350/247/204-4-8.yml +14 -0
  89. package/adapters/plugins/book299-4081-c/rules/exception/c/350/247/204-4-9.yml +14 -0
  90. package/adapters/plugins/book299-4081-c/rules/performance/c/345/273/272-5-13.yml +14 -0
  91. package/adapters/plugins/book299-4081-c/rules/performance/c/345/273/272-5-6.yml +14 -0
  92. package/adapters/plugins/book299-4081-c/rules/performance/c/345/273/272-5-7.yml +14 -0
  93. package/adapters/plugins/book299-4081-c/rules/performance/c/350/247/204-4-14.yml +14 -0
  94. package/adapters/plugins/book299-4081-c/rules/performance/c/350/247/204-4-2.yml +14 -0
  95. package/adapters/plugins/book299-4081-c/rules/resource/c/345/273/272-4-2.yml +14 -0
  96. package/adapters/plugins/book299-4081-c/rules/security/c/350/247/204-4-13.yml +14 -0
  97. package/adapters/plugins/book299-4081-c/rules/style/c/345/216/237-1-1.yml +14 -0
  98. package/adapters/plugins/book299-4081-c/rules/style/c/345/216/237-1-2.yml +14 -0
  99. package/adapters/plugins/book299-4081-c/rules/style/c/345/216/237-1-3.yml +14 -0
  100. package/adapters/plugins/book299-4081-c/rules/style/c/345/216/237-1-4.yml +14 -0
  101. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-2-1.yml +14 -0
  102. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-2-2.yml +14 -0
  103. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-2-3.yml +14 -0
  104. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-2-4.yml +14 -0
  105. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-1.yml +14 -0
  106. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-2.yml +14 -0
  107. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-3.yml +14 -0
  108. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-4.yml +14 -0
  109. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-5.yml +14 -0
  110. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-6.yml +14 -0
  111. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-7.yml +14 -0
  112. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-3-8.yml +14 -0
  113. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-4-1.yml +14 -0
  114. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-4-3.yml +14 -0
  115. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-1.yml +14 -0
  116. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-10.yml +14 -0
  117. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-11.yml +14 -0
  118. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-2.yml +14 -0
  119. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-3.yml +14 -0
  120. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-4.yml +14 -0
  121. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-5.yml +14 -0
  122. package/adapters/plugins/book299-4081-c/rules/style/c/345/273/272-5-9.yml +14 -0
  123. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-1.yml +14 -0
  124. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-10.yml +14 -0
  125. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-11.yml +14 -0
  126. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-12.yml +14 -0
  127. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-13.yml +14 -0
  128. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-14.yml +14 -0
  129. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-16.yml +14 -0
  130. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-17.yml +14 -0
  131. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-18.yml +14 -0
  132. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-19.yml +14 -0
  133. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-2.yml +14 -0
  134. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-20.yml +14 -0
  135. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-3.yml +14 -0
  136. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-4.yml +14 -0
  137. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-5.yml +14 -0
  138. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-6.yml +14 -0
  139. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-7.yml +14 -0
  140. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-8.yml +14 -0
  141. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-2-9.yml +14 -0
  142. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-1.yml +14 -0
  143. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-10.yml +14 -0
  144. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-11.yml +14 -0
  145. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-12.yml +14 -0
  146. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-13.yml +14 -0
  147. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-14.yml +14 -0
  148. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-15.yml +14 -0
  149. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-16.yml +14 -0
  150. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-17.yml +14 -0
  151. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-18.yml +14 -0
  152. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-19.yml +14 -0
  153. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-2.yml +14 -0
  154. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-20.yml +14 -0
  155. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-21.yml +14 -0
  156. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-22.yml +14 -0
  157. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-3.yml +14 -0
  158. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-4.yml +14 -0
  159. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-5.yml +14 -0
  160. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-6.yml +14 -0
  161. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-7.yml +14 -0
  162. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-8.yml +14 -0
  163. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-3-9.yml +14 -0
  164. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-1.yml +14 -0
  165. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-10.yml +14 -0
  166. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-15.yml +14 -0
  167. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-16.yml +14 -0
  168. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-17.yml +14 -0
  169. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-18.yml +14 -0
  170. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-3.yml +14 -0
  171. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-4.yml +14 -0
  172. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-5.yml +14 -0
  173. package/adapters/plugins/book299-4081-c/rules/style/c/350/247/204-4-7.yml +14 -0
  174. package/adapters/plugins/book299-4081-c/scripts/install-gradle.sh +4 -0
  175. package/adapters/plugins/book299-4081-c/scripts/install-maven.sh +20 -0
  176. package/adapters/plugins/book299-4083-javascriptes5/README.md +21 -0
  177. package/adapters/plugins/book299-4083-javascriptes5/plugin.yml +21 -0
  178. package/adapters/plugins/book299-4083-javascriptes5/rules/security/gen-0001.yml +14 -0
  179. package/adapters/plugins/book299-4083-javascriptes5/rules/security/gen-0002.yml +14 -0
  180. package/adapters/plugins/book299-4083-javascriptes5/rules/security/gen-0003.yml +14 -0
  181. package/adapters/plugins/book299-4083-javascriptes5/scripts/install-gradle.sh +4 -0
  182. package/adapters/plugins/book299-4083-javascriptes5/scripts/install-maven.sh +20 -0
  183. package/adapters/plugins/p3c-java/README.md +66 -0
  184. package/adapters/plugins/p3c-java/plugin.yml +30 -0
  185. package/adapters/plugins/p3c-java/scripts/install-gradle-p3c.sh +45 -0
  186. package/adapters/plugins/p3c-java/scripts/install-maven-p3c.sh +98 -0
  187. package/adapters/plugins/p3c-java/templates/gradle/xp-gate-p3c-gradle.gradle +68 -0
  188. package/adapters/plugins/p3c-java/templates/maven/xp-gate-p3c-profile.xml +81 -0
  189. package/adapters/plugins/whalecloud-java/README.md +98 -0
  190. package/adapters/plugins/whalecloud-java/plugin.yml +45 -0
  191. package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-001.yml +17 -0
  192. package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-002.yml +17 -0
  193. package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-003.yml +17 -0
  194. package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-004.yml +17 -0
  195. package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-005.yml +17 -0
  196. package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-006.yml +17 -0
  197. package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-007.yml +17 -0
  198. package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-008.yml +17 -0
  199. package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-009.yml +17 -0
  200. package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-010.yml +17 -0
  201. package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-011.yml +17 -0
  202. package/adapters/plugins/whalecloud-java/rules/collection/wc-collect-012.yml +17 -0
  203. package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-001.yml +17 -0
  204. package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-002.yml +17 -0
  205. package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-003.yml +17 -0
  206. package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-004.yml +17 -0
  207. package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-005.yml +17 -0
  208. package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-006.yml +17 -0
  209. package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-007.yml +17 -0
  210. package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-008.yml +17 -0
  211. package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-009.yml +17 -0
  212. package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-010.yml +17 -0
  213. package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-011.yml +17 -0
  214. package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-012.yml +17 -0
  215. package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-013.yml +17 -0
  216. package/adapters/plugins/whalecloud-java/rules/concurrency/wc-concur-014.yml +17 -0
  217. package/adapters/plugins/whalecloud-java/rules/exception/wc-except-001.yml +17 -0
  218. package/adapters/plugins/whalecloud-java/rules/exception/wc-except-002.yml +17 -0
  219. package/adapters/plugins/whalecloud-java/rules/exception/wc-except-003.yml +17 -0
  220. package/adapters/plugins/whalecloud-java/rules/exception/wc-except-004.yml +17 -0
  221. package/adapters/plugins/whalecloud-java/rules/exception/wc-except-005.yml +17 -0
  222. package/adapters/plugins/whalecloud-java/rules/exception/wc-except-006.yml +17 -0
  223. package/adapters/plugins/whalecloud-java/rules/exception/wc-except-007.yml +17 -0
  224. package/adapters/plugins/whalecloud-java/rules/exception/wc-except-008.yml +17 -0
  225. package/adapters/plugins/whalecloud-java/rules/exception/wc-except-009.yml +17 -0
  226. package/adapters/plugins/whalecloud-java/rules/exception/wc-except-010.yml +17 -0
  227. package/adapters/plugins/whalecloud-java/rules/exception/wc-except-011.yml +17 -0
  228. package/adapters/plugins/whalecloud-java/rules/logging/wc-log-001.yml +17 -0
  229. package/adapters/plugins/whalecloud-java/rules/logging/wc-log-002.yml +17 -0
  230. package/adapters/plugins/whalecloud-java/rules/logging/wc-log-003.yml +17 -0
  231. package/adapters/plugins/whalecloud-java/rules/logging/wc-log-004.yml +17 -0
  232. package/adapters/plugins/whalecloud-java/rules/logging/wc-log-005.yml +17 -0
  233. package/adapters/plugins/whalecloud-java/rules/logging/wc-log-006.yml +17 -0
  234. package/adapters/plugins/whalecloud-java/rules/logging/wc-log-007.yml +17 -0
  235. package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-001.yml +17 -0
  236. package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-002.yml +17 -0
  237. package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-003.yml +17 -0
  238. package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-004.yml +17 -0
  239. package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-005.yml +17 -0
  240. package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-006.yml +17 -0
  241. package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-007.yml +17 -0
  242. package/adapters/plugins/whalecloud-java/rules/performance/wc-perf-008.yml +17 -0
  243. package/adapters/plugins/whalecloud-java/rules/resource/wc-reso-001.yml +17 -0
  244. package/adapters/plugins/whalecloud-java/rules/resource/wc-reso-002.yml +17 -0
  245. package/adapters/plugins/whalecloud-java/rules/resource/wc-reso-003.yml +17 -0
  246. package/adapters/plugins/whalecloud-java/rules/resource/wc-reso-004.yml +17 -0
  247. package/adapters/plugins/whalecloud-java/rules/resource/wc-reso-005.yml +17 -0
  248. package/adapters/plugins/whalecloud-java/rules/resource/wc-reso-006.yml +17 -0
  249. package/adapters/plugins/whalecloud-java/rules/security/wc-secu-001.yml +17 -0
  250. package/adapters/plugins/whalecloud-java/rules/security/wc-secu-002.yml +17 -0
  251. package/adapters/plugins/whalecloud-java/rules/security/wc-secu-003.yml +17 -0
  252. package/adapters/plugins/whalecloud-java/rules/security/wc-secu-004.yml +17 -0
  253. package/adapters/plugins/whalecloud-java/rules/security/wc-secu-005.yml +17 -0
  254. package/adapters/plugins/whalecloud-java/rules/style/wc-style-001.yml +17 -0
  255. package/adapters/plugins/whalecloud-java/rules/style/wc-style-002.yml +17 -0
  256. package/adapters/plugins/whalecloud-java/rules/style/wc-style-003.yml +17 -0
  257. package/adapters/plugins/whalecloud-java/rules/style/wc-style-004.yml +17 -0
  258. package/adapters/plugins/whalecloud-java/rules/style/wc-style-005.yml +17 -0
  259. package/adapters/plugins/whalecloud-java/rules/style/wc-style-006.yml +17 -0
  260. package/adapters/plugins/whalecloud-java/rules/style/wc-style-007.yml +17 -0
  261. package/adapters/plugins/whalecloud-java/rules/style/wc-style-008.yml +17 -0
  262. package/adapters/plugins/whalecloud-java/rules/style/wc-style-009.yml +17 -0
  263. package/adapters/plugins/whalecloud-java/rules/style/wc-style-010.yml +17 -0
  264. package/adapters/plugins/whalecloud-java/rules/style/wc-style-011.yml +17 -0
  265. package/adapters/plugins/whalecloud-java/rules/style/wc-style-012.yml +17 -0
  266. package/adapters/plugins/whalecloud-java/rules/style/wc-style-013.yml +17 -0
  267. package/adapters/plugins/whalecloud-java/rules/style/wc-style-014.yml +17 -0
  268. package/adapters/plugins/whalecloud-java/rules/style/wc-style-015.yml +17 -0
  269. package/adapters/plugins/whalecloud-java/rules/style/wc-style-016.yml +17 -0
  270. package/adapters/plugins/whalecloud-java/rules/style/wc-style-017.yml +17 -0
  271. package/adapters/plugins/whalecloud-java/rules/style/wc-style-018.yml +17 -0
  272. package/adapters/plugins/whalecloud-java/scripts/install-gradle-whalecloud.sh +97 -0
  273. package/adapters/plugins/whalecloud-java/scripts/install-maven-whalecloud.sh +201 -0
  274. package/adapters/plugins/whalecloud-java/templates/gradle/xp-gate-whalecloud-gradle.gradle +73 -0
  275. package/adapters/plugins/whalecloud-java/templates/maven/xp-gate-whalecloud-profile.xml +148 -0
  276. package/bin/xp-gate.js +111 -129
  277. package/hooks/pre-commit +31 -27
  278. package/hooks/pre-push +7 -3
  279. package/lib/__tests__/baseline.test.js +123 -0
  280. package/lib/__tests__/migrate.test.js +20 -0
  281. package/lib/__tests__/ui-detector.test.ts +94 -0
  282. package/lib/__tests__/uninstall.test.js +36 -0
  283. package/lib/__tests__/update-skill.test.js +11 -0
  284. package/lib/baseline.js +392 -0
  285. package/lib/doctor.js +127 -141
  286. package/lib/gate-audit.ts +25 -8
  287. package/lib/init.js +57 -2
  288. package/lib/migrate.js +74 -73
  289. package/lib/ui-detector.ts +3 -3
  290. package/lib/uninstall.js +63 -31
  291. package/lib/update-skill.js +32 -34
  292. package/package.json +1 -1
  293. package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
  294. package/plugins/claude-code/skills/delphi-review/AGENTS.md +1 -1
  295. package/plugins/claude-code/skills/ralph-loop/SKILL.md +41 -3
  296. package/plugins/claude-code/skills/sprint-flow/AGENTS.md +1 -1
  297. package/plugins/claude-code/skills/sprint-flow/SKILL.md +178 -4
  298. package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +1 -1
  299. package/plugins/opencode/package.json +28 -4
  300. package/plugins/opencode/scripts/prepack.cjs +85 -0
  301. package/plugins/opencode/skills/delphi-review/AGENTS.md +1 -1
  302. package/plugins/opencode/skills/ralph-loop/SKILL.md +41 -3
  303. package/plugins/opencode/skills/sprint-flow/AGENTS.md +1 -1
  304. package/plugins/opencode/skills/sprint-flow/SKILL.md +178 -4
  305. package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +1 -1
  306. package/plugins/qoder/skills/delphi-review/AGENTS.md +1 -1
  307. package/plugins/qoder/skills/ralph-loop/SKILL.md +41 -3
  308. package/plugins/qoder/skills/sprint-flow/AGENTS.md +1 -1
  309. package/plugins/qoder/skills/sprint-flow/SKILL.md +147 -4
  310. package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +1 -1
  311. package/skills/delphi-review/AGENTS.md +1 -1
  312. package/skills/ralph-loop/SKILL.md +41 -3
  313. package/skills/sprint-flow/AGENTS.md +1 -1
  314. package/skills/sprint-flow/SKILL.md +178 -4
  315. package/skills/test-specification-alignment/AGENTS.md +1 -1
@@ -0,0 +1,123 @@
1
+ /**
2
+ * @test REQ-152 Baseline CLI handler
3
+ * @intent Verify baseline create/show/reset/diff commands
4
+ * @covers AC-152
5
+ */
6
+ const path = require('path');
7
+ const fs = require('fs');
8
+ const os = require('os');
9
+
10
+ const { handleBaseline, showBaseline } = require('../baseline.js');
11
+
12
+ describe('baseline.js - CLI handler', () => {
13
+ let tmpDir;
14
+ const originalCwd = process.cwd;
15
+
16
+ afterAll(() => {
17
+ process.cwd = originalCwd;
18
+ });
19
+
20
+ beforeEach(() => {
21
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'baseline-cli-test-'));
22
+ process.cwd = () => tmpDir;
23
+ });
24
+
25
+ describe('handleBaseline - help', () => {
26
+ it('prints usage when no subcommand given', async () => {
27
+ const logs = [];
28
+ const origLog = console.log;
29
+ console.log = (...args) => logs.push(args.join(' '));
30
+
31
+ const code = await handleBaseline([]);
32
+ expect(code).toBe(0);
33
+ expect(logs.some(l => l.includes('Usage'))).toBe(true);
34
+
35
+ console.log = origLog;
36
+ });
37
+
38
+ it('prints usage for --help', async () => {
39
+ const logs = [];
40
+ const origLog = console.log;
41
+ console.log = (...args) => logs.push(args.join(' '));
42
+
43
+ const code = await handleBaseline(['--help']);
44
+ expect(code).toBe(0);
45
+ expect(logs.some(l => l.includes('Usage'))).toBe(true);
46
+
47
+ console.log = origLog;
48
+ });
49
+ });
50
+
51
+ describe('handleBaseline - unknown subcommand', () => {
52
+ it('returns error for unknown subcommand', async () => {
53
+ const logs = [];
54
+ const errs = [];
55
+ const origLog = console.log;
56
+ const origErr = console.error;
57
+ console.log = (...args) => logs.push(args.join(' '));
58
+ console.error = (...args) => errs.push(args.join(' '));
59
+
60
+ const code = await handleBaseline(['unknown-cmd']);
61
+ expect(code).toBe(1);
62
+ expect(errs.some(l => l.includes('Unknown baseline subcommand'))).toBe(true);
63
+
64
+ console.log = origLog;
65
+ console.error = origErr;
66
+ });
67
+ });
68
+
69
+ describe('showBaseline - no baseline file', () => {
70
+ it('shows message when no baseline exists', () => {
71
+ const logs = [];
72
+ const origLog = console.log;
73
+ console.log = (...args) => logs.push(args.join(' '));
74
+
75
+ const code = showBaseline();
76
+ expect(code).toBe(1);
77
+ expect(logs.some(l => l.includes('No baseline'))).toBe(true);
78
+
79
+ console.log = origLog;
80
+ });
81
+ });
82
+
83
+ describe('showBaseline - with baseline file', () => {
84
+ it('shows summary when baseline exists', () => {
85
+ const baselinePath = path.join(tmpDir, '.xp-gate', 'lint-baseline.json');
86
+ fs.mkdirSync(path.dirname(baselinePath), { recursive: true });
87
+ fs.writeFileSync(baselinePath, JSON.stringify({
88
+ 'src/app.ts': {
89
+ eslint: { warnings: 3, errors: 1 },
90
+ totalWarnings: 3,
91
+ lastAnalyzed: '2026-06-01T12:00:00.000Z',
92
+ },
93
+ }));
94
+
95
+ const logs = [];
96
+ const origLog = console.log;
97
+ console.log = (...args) => logs.push(args.join(' '));
98
+
99
+ const code = showBaseline();
100
+ expect(code).toBe(0);
101
+ expect(logs.some(l => l.includes('3'))).toBe(true);
102
+ expect(logs.some(l => l.includes('ESLint'))).toBe(true);
103
+
104
+ console.log = origLog;
105
+ });
106
+
107
+ it('shows empty message for baseline with no entries', () => {
108
+ const baselinePath = path.join(tmpDir, '.xp-gate', 'lint-baseline.json');
109
+ fs.mkdirSync(path.dirname(baselinePath), { recursive: true });
110
+ fs.writeFileSync(baselinePath, '{}');
111
+
112
+ const logs = [];
113
+ const origLog = console.log;
114
+ console.log = (...args) => logs.push(args.join(' '));
115
+
116
+ const code = showBaseline();
117
+ expect(code).toBe(0);
118
+ expect(logs.some(l => l.includes('empty'))).toBe(true);
119
+
120
+ console.log = origLog;
121
+ });
122
+ });
123
+ });
@@ -193,6 +193,26 @@ describe('migrate', () => {
193
193
 
194
194
  // === Print summary ===
195
195
 
196
+ // === Phase isolation: removing npmrc should not affect cache check ===
197
+
198
+ it('phases are isolated: npmrc cleanup and cache check operate independently', async () => {
199
+ // Only npmrc has github packages lines, no cache dir
200
+ fs.writeFileSync(npmrcPath(), [
201
+ '//npm.pkg.github.com/:_authToken=ghp_abc123',
202
+ 'registry=https://registry.npmjs.org/'
203
+ ].join('\n') + '\n');
204
+
205
+ const { migrate } = require('../migrate');
206
+ const result = await migrate([]);
207
+
208
+ expect(result).toBe(0);
209
+ // npmrc should be cleaned
210
+ const content = fs.readFileSync(npmrcPath(), 'utf8');
211
+ expect(content).not.toContain('npm.pkg.github.com');
212
+ // Should report no old cache (dir doesn't exist)
213
+ expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('No old cache'));
214
+ });
215
+
196
216
  it('prints full summary of actions taken', async () => {
197
217
  fs.writeFileSync(npmrcPath(), [
198
218
  '//npm.pkg.github.com/:_authToken=ghp_abc123',
@@ -357,4 +357,98 @@ describe('ui-detector', () => {
357
357
  expect(isExcluded('src/Button.test.tsx', ['**/*.test.*'])).toBe(true);
358
358
  });
359
359
  });
360
+
361
+ /**
362
+ * @test #172 ui-detector CLI coverage
363
+ * @intent Cover CLI entry points (runCli, runPushMode, processOutput, runCheckBranch, runDefault)
364
+ * via real subprocess execution with NODE_V8_COVERAGE to merge coverage profiles.
365
+ * @covers ui-detector-cli-push-mode, ui-detector-cli-check-branch, ui-detector-cli-default-mode
366
+ */
367
+ describe('CLI integration (subprocess)', () => {
368
+ const { spawnSync: realSpawnSync } = require('child_process') as typeof import('child_process');
369
+ const path = require('path') as typeof import('path');
370
+ const fs = require('fs') as typeof import('fs');
371
+ const os = require('os') as typeof import('os');
372
+
373
+ const UI_DETECTOR_PATH = path.resolve(__dirname, '../ui-detector.ts');
374
+
375
+ function runCli(args: string[], stdin?: string, cwd?: string): { code: number; stdout: string; stderr: string } {
376
+ const coverageDir = process.env.NODE_V8_COVERAGE ?? path.join(process.cwd(), 'coverage', '.tmp');
377
+ const result = realSpawnSync('npx', ['tsx', UI_DETECTOR_PATH, ...args], {
378
+ cwd: cwd ?? process.cwd(),
379
+ encoding: 'utf-8',
380
+ input: stdin,
381
+ env: { ...process.env, NODE_V8_COVERAGE: coverageDir },
382
+ });
383
+ return {
384
+ code: result.status ?? -1,
385
+ stdout: result.stdout ?? '',
386
+ stderr: result.stderr ?? '',
387
+ };
388
+ }
389
+
390
+ it('runs default mode with --check-branch flag (HEAD-based detection)', () => {
391
+ const { code, stdout } = runCli(['--check-branch']);
392
+ expect(code).toBeGreaterThanOrEqual(0);
393
+ expect(code).toBeLessThanOrEqual(1);
394
+ const parsed = JSON.parse(stdout);
395
+ expect(parsed).toHaveProperty('isUiSprint');
396
+ expect(parsed).toHaveProperty('matchedFiles');
397
+ expect(parsed).toHaveProperty('matchedRules');
398
+ });
399
+
400
+ it('runs push-mode via stdin', () => {
401
+ const { code, stdout } = runCli(['--push-mode'], 'views/index.html');
402
+ expect([0, 1]).toContain(code);
403
+ const parsed = JSON.parse(stdout);
404
+ expect(parsed.isUiSprint).toBe(true);
405
+ expect(parsed.matchedFiles).toContain('views/index.html');
406
+ });
407
+
408
+ it('runs push-mode with stdin input', () => {
409
+ const { code, stdout } = runCli(['--push-mode'], 'views/login.njk\nsrc/auth.ts\n');
410
+ expect([0, 1]).toContain(code);
411
+ const parsed = JSON.parse(stdout);
412
+ expect(parsed.isUiSprint).toBe(true);
413
+ expect(parsed.matchedFiles).toContain('views/login.njk');
414
+ });
415
+
416
+ it('runs push-mode with non-UI files (exit 1)', () => {
417
+ const { code, stdout } = runCli(['--push-mode'], 'src/auth.ts\nsrc/db.ts\n');
418
+ expect(code).toBe(1);
419
+ const parsed = JSON.parse(stdout);
420
+ expect(parsed.isUiSprint).toBe(false);
421
+ expect(parsed.matchedFiles).toEqual([]);
422
+ });
423
+
424
+ it('respects .ui-gate-ignore in push-mode', () => {
425
+ const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'ui-detector-ignore-'));
426
+ try {
427
+ fs.writeFileSync(path.join(tmp, '.ui-gate-ignore'), 'legacy/**\n');
428
+ const { code, stdout } = runCli(['--push-mode'], 'legacy/views/index.html', tmp);
429
+ expect(code).toBe(1);
430
+ const parsed = JSON.parse(stdout);
431
+ expect(parsed.isUiSprint).toBe(false);
432
+ } finally {
433
+ fs.rmSync(tmp, { recursive: true, force: true });
434
+ }
435
+ });
436
+
437
+ it('processes renamed files in push-mode', () => {
438
+ const { code, stdout } = runCli(['--push-mode'], 'src/a.tsx \u2192 src/components/B.tsx');
439
+ expect([0, 1]).toContain(code);
440
+ const parsed = JSON.parse(stdout);
441
+ expect(parsed.matchedFiles).toContain('src/components/B.tsx');
442
+ });
443
+
444
+ it('runs default mode (detectUiSprint in current repo)', () => {
445
+ const { code, stdout } = runCli([]);
446
+ expect([0, 1]).toContain(code);
447
+ const parsed = JSON.parse(stdout);
448
+ expect(parsed).toHaveProperty('isUiSprint');
449
+ expect(parsed).toHaveProperty('matchedFiles');
450
+ expect(parsed).toHaveProperty('matchedRules');
451
+ });
452
+ });
360
453
  });
454
+
@@ -577,6 +577,42 @@ describe('uninstall', () => {
577
577
  expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('adapter-common.sh'));
578
578
  });
579
579
 
580
+ // === Execution loop: mixed item types plan ===
581
+
582
+ it('executes mixed-type plan (file + dir + gitconfig items) correctly', async () => {
583
+ setupGlobalInstall();
584
+ const expectedHooksPath = globalHooksDir();
585
+ mockExecGlobalHooksPath(expectedHooksPath);
586
+ const { uninstall } = require('../uninstall');
587
+
588
+ const result = await uninstall([]);
589
+
590
+ expect(result).toBe(0);
591
+
592
+ // Gitconfig type unset core.hooksPath
593
+ expect(execSpy).toHaveBeenCalledWith(
594
+ expect.stringContaining('git config --global --unset core.hooksPath'),
595
+ expect.any(Object)
596
+ );
597
+ // Dir items removed: global hooks, adapters, template
598
+ expect(fs.existsSync(globalHooksDir())).toBe(false);
599
+ expect(fs.existsSync(globalAdaptersDir())).toBe(false);
600
+ expect(fs.existsSync(templateDir())).toBe(false);
601
+ });
602
+
603
+ it('skips non-existent file items in execution loop gracefully', async () => {
604
+ setupLocalInstall();
605
+ // Delete one file before uninstall
606
+ fs.unlinkSync(path.join(projectHooksDir(), 'pre-commit'));
607
+ mockExecSuccess();
608
+ const { uninstall } = require('../uninstall');
609
+
610
+ const result = await uninstall([]);
611
+ expect(result).toBe(0);
612
+ // Should not crash — remaining items still processed
613
+ expect(fs.existsSync(path.join(projectHooksDir(), 'pre-push'))).toBe(false);
614
+ });
615
+
580
616
  it('saves rollback snapshot before destructive operations', async () => {
581
617
  setupLocalInstall();
582
618
  mockExecSuccess();
@@ -263,6 +263,17 @@ describe('update-skill', () => {
263
263
  expect(errorSpy).toHaveBeenCalledWith('Error: foo is not installed');
264
264
  });
265
265
 
266
+ // === Mode handler isolation: check/all/single operate independently ===
267
+
268
+ it('check and all modes handle empty config without crashing (edge cases)', async () => {
269
+ // No config file at all — getConfig returns {}
270
+ const { updateSkill } = require('../update-skill');
271
+ expect(await updateSkill(null, { check: true })).toBe(0);
272
+ expect(await updateSkill(null, { all: true })).toBe(0);
273
+ expect(await updateSkill('anything')).toBe(1);
274
+ expect(errorSpy).toHaveBeenCalledWith('Error: anything is not installed');
275
+ });
276
+
266
277
  it('getConfig parses valid config (single-name path succeeds)', async () => {
267
278
  writeConfig({ foo: { version: '1.0.0' } });
268
279
  const { updateSkill } = require('../update-skill');
@@ -0,0 +1,392 @@
1
+ /**
2
+ * baseline.js — `xp-gate baseline` CLI handler
3
+ *
4
+ * Manages per-project lint baselines stored in .xp-gate/lint-baseline.json.
5
+ *
6
+ * Commands:
7
+ * xp-gate baseline create — Full-repo scan → save baseline
8
+ * xp-gate baseline show — Display current baseline
9
+ * xp-gate baseline reset — Force re-scan and replace baseline
10
+ * xp-gate baseline diff — Diff current state against stored baseline
11
+ */
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const { execSync } = require('child_process');
16
+
17
+ function getXpGateDir() {
18
+ return path.join(process.cwd(), '.xp-gate');
19
+ }
20
+
21
+ function getBaselineFile() {
22
+ return path.join(getXpGateDir(), 'lint-baseline.json');
23
+ }
24
+
25
+ function ensureDir(dirPath) {
26
+ if (!fs.existsSync(dirPath)) {
27
+ fs.mkdirSync(dirPath, { recursive: true });
28
+ }
29
+ }
30
+
31
+ function parseArgs(subargs) {
32
+ return {
33
+ tool: subargs[0] || null,
34
+ rest: subargs.slice(1),
35
+ };
36
+ }
37
+
38
+ /**
39
+ * Run a lint tool and return its JSON output.
40
+ */
41
+ function runToolJson(toolCmd, pipeToJsonFlag) {
42
+ try {
43
+ const cmd = `${toolCmd} ${pipeToJsonFlag}`;
44
+ return execSync(cmd, { encoding: 'utf8', maxBuffer: 10 * 1024 * 1024 }).trim();
45
+ } catch (e) {
46
+ // Lint tools exit non-zero when they find issues - that's expected
47
+ if (e.stdout) return e.stdout.trim();
48
+ return '';
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Collect all source files for a given language.
54
+ */
55
+ function findFilesByExt(extensions) {
56
+ try {
57
+ const patterns = extensions.map(e => `"**/*${e}"`).join(' ');
58
+ const result = execSync(`git ls-files ${patterns}`, {
59
+ encoding: 'utf8',
60
+ maxBuffer: 5 * 1024 * 1024,
61
+ }).trim();
62
+ return result ? result.split('\n') : [];
63
+ } catch {
64
+ return [];
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Create baseline: scan all source files with available lint tools.
70
+ * Called by: xp-gate baseline create|reset
71
+ */
72
+ async function createBaseline() {
73
+ ensureDir(getXpGateDir());
74
+
75
+ const baseline = {};
76
+
77
+ // TypeScript/JavaScript — ESLint
78
+ const tsFiles = findFilesByExt(['.ts', '.tsx', '.js', '.jsx']);
79
+ if (tsFiles.length > 0) {
80
+ try {
81
+ const eslintConfigExists = fs.existsSync('.eslintrc.json') ||
82
+ fs.existsSync('.eslintrc.js') ||
83
+ fs.existsSync('.eslintrc.cjs') ||
84
+ fs.existsSync('eslint.config.js');
85
+ const eslintBin = fs.existsSync('node_modules/.bin/eslint') ? 'node_modules/.bin/eslint' : null;
86
+
87
+ if (eslintConfigExists && (eslintBin || execSync('npx eslint --version', { encoding: 'utf8' }))) {
88
+ const eslintCmd = eslintBin || 'npx eslint';
89
+ const output = runToolJson(`${eslintCmd} ${tsFiles.join(' ')}`, '-f json --no-warn-ignored');
90
+ if (output && output !== '[]') {
91
+ const parsed = JSON.parse(output);
92
+ for (const fileResult of parsed) {
93
+ const relativePath = fileResult.filePath;
94
+ const fileName = tsFiles.find(f => relativePath.endsWith(f));
95
+ if (!fileName) continue;
96
+
97
+ baseline[fileName] = {
98
+ eslint: {
99
+ warnings: fileResult.warningCount || 0,
100
+ errors: fileResult.errorCount || 0,
101
+ },
102
+ totalWarnings: fileResult.warningCount || 0,
103
+ lastAnalyzed: new Date().toISOString(),
104
+ };
105
+ }
106
+ }
107
+ }
108
+ } catch {
109
+ // ESLint unavailable — skip
110
+ }
111
+ }
112
+
113
+ // Python — ruff
114
+ const pyFiles = findFilesByExt(['.py']);
115
+ if (pyFiles.length > 0) {
116
+ try {
117
+ execSync('ruff --version', { encoding: 'utf8' });
118
+ const output = runToolJson(`ruff check ${pyFiles.join(' ')}`, '--output-format json');
119
+ if (output && output !== '[]') {
120
+ const parsed = JSON.parse(output);
121
+ for (const fileResult of parsed) {
122
+ if (!baseline[fileResult.file]) {
123
+ const messages = fileResult.messages || [];
124
+ baseline[fileResult.file] = {
125
+ ruff: { warnings: messages.length, errors: 0 },
126
+ totalWarnings: messages.length,
127
+ lastAnalyzed: new Date().toISOString(),
128
+ };
129
+ } else {
130
+ const messages = fileResult.messages || [];
131
+ baseline[fileResult.file].ruff = { warnings: messages.length, errors: 0 };
132
+ baseline[fileResult.file].totalWarnings += messages.length;
133
+ }
134
+ }
135
+ }
136
+ } catch {
137
+ // Ruff unavailable — skip
138
+ }
139
+ }
140
+
141
+ // Go — golangci-lint
142
+ const goFiles = findFilesByExt(['.go']);
143
+ if (goFiles.length > 0) {
144
+ try {
145
+ execSync('golangci-lint --version', { encoding: 'utf8' });
146
+ const output = runToolJson('golangci-lint run', '--out-format json');
147
+ if (output) {
148
+ const parsed = JSON.parse(output).Issues || [];
149
+ const warningsByFile = {};
150
+ for (const issue of parsed) {
151
+ const matchedFile = goFiles.find(f => issue.file.endsWith(f));
152
+ if (!matchedFile) continue;
153
+ if (!warningsByFile[matchedFile]) {
154
+ warningsByFile[matchedFile] = { warnings: 0, errors: 0 };
155
+ }
156
+ if (issue.severity === 'error') {
157
+ warningsByFile[matchedFile].errors++;
158
+ } else {
159
+ warningsByFile[matchedFile].warnings++;
160
+ }
161
+ }
162
+ for (const [file, counts] of Object.entries(warningsByFile)) {
163
+ if (baseline[file]) {
164
+ baseline[file].golangci = counts;
165
+ baseline[file].totalWarnings += counts.warnings;
166
+ } else {
167
+ baseline[file] = {
168
+ golangci: counts,
169
+ totalWarnings: counts.warnings,
170
+ lastAnalyzed: new Date().toISOString(),
171
+ };
172
+ }
173
+ }
174
+ }
175
+ } catch {
176
+ // golangci-lint unavailable — skip
177
+ }
178
+ }
179
+
180
+ // Shell — shellcheck
181
+ const shFiles = findFilesByExt(['.sh']);
182
+ if (shFiles.length > 0) {
183
+ try {
184
+ execSync('shellcheck --version', { encoding: 'utf8' });
185
+ const output = runToolJson(`shellcheck -f json ${shFiles.join(' ')}`, '');
186
+ if (output && output !== '[]') {
187
+ const parsed = JSON.parse(output);
188
+ const warningsByFile = {};
189
+ for (const item of parsed) {
190
+ const matchedFile = shFiles.find(f => item.file.endsWith(f));
191
+ if (!matchedFile) continue;
192
+ if (!warningsByFile[matchedFile]) {
193
+ warningsByFile[matchedFile] = { warnings: 0, errors: 0 };
194
+ }
195
+ if (item.level === 'error') {
196
+ warningsByFile[matchedFile].errors++;
197
+ } else {
198
+ warningsByFile[matchedFile].warnings++;
199
+ }
200
+ }
201
+ for (const [file, counts] of Object.entries(warningsByFile)) {
202
+ if (baseline[file]) {
203
+ baseline[file].shellcheck = counts;
204
+ baseline[file].totalWarnings += counts.warnings;
205
+ } else {
206
+ baseline[file] = {
207
+ shellcheck: counts,
208
+ totalWarnings: counts.warnings,
209
+ lastAnalyzed: new Date().toISOString(),
210
+ };
211
+ }
212
+ }
213
+ }
214
+ } catch {
215
+ // shellcheck unavailable — skip
216
+ }
217
+ }
218
+
219
+ fs.writeFileSync(getBaselineFile(), JSON.stringify(baseline, null, 2));
220
+ return baseline;
221
+ }
222
+
223
+ /**
224
+ * Show current baseline.
225
+ */
226
+ function showBaseline() {
227
+ if (!fs.existsSync(getBaselineFile())) {
228
+ console.log('No baseline found. Run `xp-gate baseline create` to initialize.');
229
+ return 1;
230
+ }
231
+
232
+ const data = JSON.parse(fs.readFileSync(getBaselineFile(), 'utf8'));
233
+ const files = Object.keys(data);
234
+
235
+ if (files.length === 0) {
236
+ console.log('Baseline is empty (no lint issues found on last scan).');
237
+ return 0;
238
+ }
239
+
240
+ const totalWarnings = files.reduce((s, f) => s + data[f].totalWarnings, 0);
241
+ let eslintCount = 0;
242
+ let ruffCount = 0;
243
+ let golangciCount = 0;
244
+ let shellcheckCount = 0;
245
+
246
+ for (const entry of Object.values(data)) {
247
+ if (entry.eslint) eslintCount++;
248
+ if (entry.ruff) ruffCount++;
249
+ if (entry.golangci) golangciCount++;
250
+ if (entry.shellcheck) shellcheckCount++;
251
+ }
252
+
253
+ console.log('Lint Baseline:');
254
+ console.log(` Created: ${data[files[0]]?.lastAnalyzed?.slice(0, 10) || 'N/A'}`);
255
+ console.log(` Files tracked: ${files.length}`);
256
+ console.log(` Total warnings: ${totalWarnings}`);
257
+ if (eslintCount > 0) console.log(` ESLint: ${eslintCount} files`);
258
+ if (ruffCount > 0) console.log(` Ruff: ${ruffCount} files`);
259
+ if (golangciCount > 0) console.log(` golangci-lint: ${golangciCount} files`);
260
+ if (shellcheckCount > 0) console.log(` ShellCheck: ${shellcheckCount} files`);
261
+
262
+ return 0;
263
+ }
264
+
265
+ /**
266
+ * Reset baseline: force re-scan and replace.
267
+ */
268
+ async function resetBaseline() {
269
+ const baseline = await createBaseline();
270
+ console.log(`Baseline reset. ${Object.keys(baseline).length} files tracked.`);
271
+ return 0;
272
+ }
273
+
274
+ /**
275
+ * Diff current lint state against stored baseline.
276
+ */
277
+ async function diffBaseline() {
278
+ if (!fs.existsSync(getBaselineFile())) {
279
+ console.log('No baseline found. Run `xp-gate baseline create` first.');
280
+ return 1;
281
+ }
282
+
283
+ const oldBaseline = JSON.parse(fs.readFileSync(getBaselineFile(), 'utf8'));
284
+ const currentBaseline = await createBaseline();
285
+
286
+ const allFiles = new Set([
287
+ ...Object.keys(oldBaseline),
288
+ ...Object.keys(currentBaseline),
289
+ ]);
290
+
291
+ let totalWarningsDelta = 0;
292
+ const increased = [];
293
+ const decreased = [];
294
+ const added = [];
295
+ const removed = [];
296
+
297
+ for (const file of allFiles) {
298
+ const oldW = oldBaseline[file]?.totalWarnings || 0;
299
+ const newW = currentBaseline[file]?.totalWarnings || 0;
300
+ const delta = newW - oldW;
301
+
302
+ totalWarningsDelta += delta;
303
+
304
+ if (!oldBaseline[file] && currentBaseline[file]) {
305
+ added.push(` + ${file} (${newW} warnings)`);
306
+ } else if (oldBaseline[file] && !currentBaseline[file]) {
307
+ removed.push(` - ${file} (all ${oldW} warnings cleared)`);
308
+ } else if (delta > 0) {
309
+ increased.push(` ↑ ${file} (${oldW} → ${newW}, +${delta})`);
310
+ } else if (delta < 0) {
311
+ decreased.push(` ↓ ${file} (${oldW} → ${newW}, ${delta})`);
312
+ }
313
+ }
314
+
315
+ console.log('Lint Baseline Diff:');
316
+ console.log(` Total warnings delta: ${totalWarningsDelta >= 0 ? '+' : ''}${totalWarningsDelta}`);
317
+
318
+ if (added.length > 0) {
319
+ console.log(`\nFiles added (${added.length}):`);
320
+ added.forEach(l => console.log(l));
321
+ }
322
+ if (removed.length > 0) {
323
+ console.log(`\nFiles removed (${removed.length}):`);
324
+ removed.forEach(l => console.log(l));
325
+ }
326
+ if (increased.length > 0) {
327
+ console.log(`\nWarnings increased (${increased.length}):`);
328
+ increased.forEach(l => console.log(l));
329
+ }
330
+ if (decreased.length > 0) {
331
+ console.log(`\nWarnings decreased (${decreased.length}):`);
332
+ decreased.forEach(l => console.log(l));
333
+ }
334
+
335
+ if (added.length === 0 && removed.length === 0 && increased.length === 0 && decreased.length === 0) {
336
+ console.log(' No change from baseline.');
337
+ }
338
+
339
+ return totalWarningsDelta > 0 ? 1 : 0;
340
+ }
341
+
342
+ /**
343
+ * Main handler called from xp-gate CLI.
344
+ * @param {string[]} subargs CLI sub-arguments
345
+ * @returns {Promise<number>} exit code
346
+ */
347
+ async function handleBaseline(subargs) {
348
+ const { tool, rest } = parseArgs(subargs);
349
+
350
+ switch (tool) {
351
+ case 'create':
352
+ console.log('Creating lint baseline...');
353
+ const created = await createBaseline();
354
+ console.log(`✅ Baseline created — ${Object.keys(created).length} files tracked.`);
355
+ return 0;
356
+
357
+ case 'show':
358
+ return showBaseline();
359
+
360
+ case 'reset':
361
+ console.log('Resetting lint baseline...');
362
+ return resetBaseline();
363
+
364
+ case 'diff':
365
+ return diffBaseline();
366
+
367
+ case 'help':
368
+ case '--help':
369
+ case null:
370
+ console.log(`Usage: xp-gate baseline <subcommand>
371
+
372
+ Subcommands:
373
+ create Scan all source files and save lint baseline
374
+ show Display current lint baseline summary
375
+ reset Force re-scan and replace baseline
376
+ diff Compare current lint state against baseline
377
+
378
+ Examples:
379
+ xp-gate baseline create
380
+ xp-gate baseline show
381
+ xp-gate baseline reset
382
+ xp-gate baseline diff`);
383
+ return 0;
384
+
385
+ default:
386
+ console.error(`Unknown baseline subcommand: ${tool}`);
387
+ console.error('Run `xp-gate baseline --help` for usage.');
388
+ return 1;
389
+ }
390
+ }
391
+
392
+ module.exports = { handleBaseline, createBaseline, showBaseline, resetBaseline, diffBaseline };