@kevinrabun/judges 3.38.0 → 3.41.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 (379) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +5 -4
  3. package/dist/api.d.ts +5 -2
  4. package/dist/api.d.ts.map +1 -1
  5. package/dist/api.js +5 -1
  6. package/dist/api.js.map +1 -1
  7. package/dist/ast/structural-parser.js +3 -3
  8. package/dist/ast/structural-parser.js.map +1 -1
  9. package/dist/calibration.d.ts +35 -0
  10. package/dist/calibration.d.ts.map +1 -1
  11. package/dist/calibration.js +52 -0
  12. package/dist/calibration.js.map +1 -1
  13. package/dist/cli.d.ts.map +1 -1
  14. package/dist/cli.js +370 -16
  15. package/dist/cli.js.map +1 -1
  16. package/dist/commands/auto-calibrate.d.ts +15 -0
  17. package/dist/commands/auto-calibrate.d.ts.map +1 -0
  18. package/dist/commands/auto-calibrate.js +107 -0
  19. package/dist/commands/auto-calibrate.js.map +1 -0
  20. package/dist/commands/benchmark-languages.js +4 -4
  21. package/dist/commands/benchmark.d.ts +2 -1
  22. package/dist/commands/benchmark.d.ts.map +1 -1
  23. package/dist/commands/benchmark.js +67 -2
  24. package/dist/commands/benchmark.js.map +1 -1
  25. package/dist/commands/calibration-dashboard.d.ts.map +1 -1
  26. package/dist/commands/calibration-dashboard.js +198 -0
  27. package/dist/commands/calibration-dashboard.js.map +1 -1
  28. package/dist/commands/calibration-share.d.ts +31 -0
  29. package/dist/commands/calibration-share.d.ts.map +1 -0
  30. package/dist/commands/calibration-share.js +183 -0
  31. package/dist/commands/calibration-share.js.map +1 -0
  32. package/dist/commands/compliance-report.d.ts +35 -0
  33. package/dist/commands/compliance-report.d.ts.map +1 -0
  34. package/dist/commands/compliance-report.js +162 -0
  35. package/dist/commands/compliance-report.js.map +1 -0
  36. package/dist/commands/config-migrate.d.ts +44 -0
  37. package/dist/commands/config-migrate.d.ts.map +1 -0
  38. package/dist/commands/config-migrate.js +241 -0
  39. package/dist/commands/config-migrate.js.map +1 -0
  40. package/dist/commands/dedup-report.d.ts +13 -0
  41. package/dist/commands/dedup-report.d.ts.map +1 -0
  42. package/dist/commands/dedup-report.js +138 -0
  43. package/dist/commands/dedup-report.js.map +1 -0
  44. package/dist/commands/dep-audit.d.ts +53 -0
  45. package/dist/commands/dep-audit.d.ts.map +1 -0
  46. package/dist/commands/dep-audit.js +278 -0
  47. package/dist/commands/dep-audit.js.map +1 -0
  48. package/dist/commands/deprecated.d.ts +48 -0
  49. package/dist/commands/deprecated.d.ts.map +1 -0
  50. package/dist/commands/deprecated.js +202 -0
  51. package/dist/commands/deprecated.js.map +1 -0
  52. package/dist/commands/diff.d.ts.map +1 -1
  53. package/dist/commands/diff.js +8 -3
  54. package/dist/commands/diff.js.map +1 -1
  55. package/dist/commands/feedback-rules.d.ts +29 -0
  56. package/dist/commands/feedback-rules.d.ts.map +1 -0
  57. package/dist/commands/feedback-rules.js +174 -0
  58. package/dist/commands/feedback-rules.js.map +1 -0
  59. package/dist/commands/feedback.d.ts +12 -0
  60. package/dist/commands/feedback.d.ts.map +1 -1
  61. package/dist/commands/feedback.js +16 -0
  62. package/dist/commands/feedback.js.map +1 -1
  63. package/dist/commands/fix-pr.d.ts +23 -0
  64. package/dist/commands/fix-pr.d.ts.map +1 -0
  65. package/dist/commands/fix-pr.js +323 -0
  66. package/dist/commands/fix-pr.js.map +1 -0
  67. package/dist/commands/fix.d.ts.map +1 -1
  68. package/dist/commands/fix.js +33 -1
  69. package/dist/commands/fix.js.map +1 -1
  70. package/dist/commands/governance.d.ts +32 -0
  71. package/dist/commands/governance.d.ts.map +1 -0
  72. package/dist/commands/governance.js +203 -0
  73. package/dist/commands/governance.js.map +1 -0
  74. package/dist/commands/help.d.ts +8 -0
  75. package/dist/commands/help.d.ts.map +1 -0
  76. package/dist/commands/help.js +303 -0
  77. package/dist/commands/help.js.map +1 -0
  78. package/dist/commands/hook.d.ts.map +1 -1
  79. package/dist/commands/hook.js +17 -20
  80. package/dist/commands/hook.js.map +1 -1
  81. package/dist/commands/interactive-fix.d.ts +23 -0
  82. package/dist/commands/interactive-fix.d.ts.map +1 -0
  83. package/dist/commands/interactive-fix.js +140 -0
  84. package/dist/commands/interactive-fix.js.map +1 -0
  85. package/dist/commands/llm-benchmark.d.ts +119 -0
  86. package/dist/commands/llm-benchmark.d.ts.map +1 -0
  87. package/dist/commands/llm-benchmark.js +396 -0
  88. package/dist/commands/llm-benchmark.js.map +1 -0
  89. package/dist/commands/metrics-dashboard.d.ts +22 -0
  90. package/dist/commands/metrics-dashboard.d.ts.map +1 -0
  91. package/dist/commands/metrics-dashboard.js +335 -0
  92. package/dist/commands/metrics-dashboard.js.map +1 -0
  93. package/dist/commands/metrics.d.ts +58 -0
  94. package/dist/commands/metrics.d.ts.map +1 -0
  95. package/dist/commands/metrics.js +242 -0
  96. package/dist/commands/metrics.js.map +1 -0
  97. package/dist/commands/monorepo.d.ts +38 -0
  98. package/dist/commands/monorepo.d.ts.map +1 -0
  99. package/dist/commands/monorepo.js +233 -0
  100. package/dist/commands/monorepo.js.map +1 -0
  101. package/dist/commands/notify.d.ts +79 -0
  102. package/dist/commands/notify.d.ts.map +1 -0
  103. package/dist/commands/notify.js +325 -0
  104. package/dist/commands/notify.js.map +1 -0
  105. package/dist/commands/onboard.d.ts +13 -0
  106. package/dist/commands/onboard.d.ts.map +1 -0
  107. package/dist/commands/onboard.js +179 -0
  108. package/dist/commands/onboard.js.map +1 -0
  109. package/dist/commands/org-metrics.d.ts +24 -0
  110. package/dist/commands/org-metrics.d.ts.map +1 -0
  111. package/dist/commands/org-metrics.js +238 -0
  112. package/dist/commands/org-metrics.js.map +1 -0
  113. package/dist/commands/override.d.ts +62 -0
  114. package/dist/commands/override.d.ts.map +1 -0
  115. package/dist/commands/override.js +264 -0
  116. package/dist/commands/override.js.map +1 -0
  117. package/dist/commands/parity.d.ts +31 -0
  118. package/dist/commands/parity.d.ts.map +1 -0
  119. package/dist/commands/parity.js +213 -0
  120. package/dist/commands/parity.js.map +1 -0
  121. package/dist/commands/plugin-search.d.ts +40 -0
  122. package/dist/commands/plugin-search.d.ts.map +1 -0
  123. package/dist/commands/plugin-search.js +328 -0
  124. package/dist/commands/plugin-search.js.map +1 -0
  125. package/dist/commands/plugins.d.ts +13 -0
  126. package/dist/commands/plugins.d.ts.map +1 -0
  127. package/dist/commands/plugins.js +105 -0
  128. package/dist/commands/plugins.js.map +1 -0
  129. package/dist/commands/quality-gate.d.ts +70 -0
  130. package/dist/commands/quality-gate.d.ts.map +1 -0
  131. package/dist/commands/quality-gate.js +264 -0
  132. package/dist/commands/quality-gate.js.map +1 -0
  133. package/dist/commands/review.js +1 -1
  134. package/dist/commands/review.js.map +1 -1
  135. package/dist/commands/snapshot.d.ts +27 -0
  136. package/dist/commands/snapshot.d.ts.map +1 -1
  137. package/dist/commands/snapshot.js +99 -0
  138. package/dist/commands/snapshot.js.map +1 -1
  139. package/dist/commands/trace.d.ts +65 -0
  140. package/dist/commands/trace.d.ts.map +1 -0
  141. package/dist/commands/trace.js +246 -0
  142. package/dist/commands/trace.js.map +1 -0
  143. package/dist/commands/trust-ramp.d.ts +30 -0
  144. package/dist/commands/trust-ramp.d.ts.map +1 -0
  145. package/dist/commands/trust-ramp.js +190 -0
  146. package/dist/commands/trust-ramp.js.map +1 -0
  147. package/dist/config.d.ts +5 -0
  148. package/dist/config.d.ts.map +1 -1
  149. package/dist/config.js +65 -0
  150. package/dist/config.js.map +1 -1
  151. package/dist/data-adapter.d.ts +124 -0
  152. package/dist/data-adapter.d.ts.map +1 -0
  153. package/dist/data-adapter.js +213 -0
  154. package/dist/data-adapter.js.map +1 -0
  155. package/dist/evaluators/accessibility.js +1 -1
  156. package/dist/evaluators/accessibility.js.map +1 -1
  157. package/dist/evaluators/ai-code-safety.d.ts.map +1 -1
  158. package/dist/evaluators/ai-code-safety.js +1 -4
  159. package/dist/evaluators/ai-code-safety.js.map +1 -1
  160. package/dist/evaluators/cost-effectiveness.js +1 -1
  161. package/dist/evaluators/cost-effectiveness.js.map +1 -1
  162. package/dist/evaluators/false-positive-review.js +4 -4
  163. package/dist/evaluators/false-positive-review.js.map +1 -1
  164. package/dist/evaluators/framework-rules.d.ts +59 -0
  165. package/dist/evaluators/framework-rules.d.ts.map +1 -0
  166. package/dist/evaluators/framework-rules.js +292 -0
  167. package/dist/evaluators/framework-rules.js.map +1 -0
  168. package/dist/evaluators/iac-security.js +1 -1
  169. package/dist/evaluators/iac-security.js.map +1 -1
  170. package/dist/evaluators/index.d.ts.map +1 -1
  171. package/dist/evaluators/index.js +59 -10
  172. package/dist/evaluators/index.js.map +1 -1
  173. package/dist/evaluators/intent-alignment.d.ts +4 -0
  174. package/dist/evaluators/intent-alignment.d.ts.map +1 -1
  175. package/dist/evaluators/intent-alignment.js +163 -0
  176. package/dist/evaluators/intent-alignment.js.map +1 -1
  177. package/dist/evaluators/logic-review.js +1 -1
  178. package/dist/evaluators/logic-review.js.map +1 -1
  179. package/dist/evaluators/maintainability.js +1 -1
  180. package/dist/evaluators/maintainability.js.map +1 -1
  181. package/dist/evaluators/over-engineering.js +3 -3
  182. package/dist/evaluators/over-engineering.js.map +1 -1
  183. package/dist/evaluators/project.d.ts +12 -0
  184. package/dist/evaluators/project.d.ts.map +1 -1
  185. package/dist/evaluators/project.js +86 -0
  186. package/dist/evaluators/project.js.map +1 -1
  187. package/dist/evaluators/security.js +2 -2
  188. package/dist/evaluators/security.js.map +1 -1
  189. package/dist/evaluators/ux.js +1 -1
  190. package/dist/evaluators/ux.js.map +1 -1
  191. package/dist/finding-lifecycle.d.ts +9 -0
  192. package/dist/finding-lifecycle.d.ts.map +1 -1
  193. package/dist/finding-lifecycle.js +15 -0
  194. package/dist/finding-lifecycle.js.map +1 -1
  195. package/dist/fix-history.d.ts +9 -0
  196. package/dist/fix-history.d.ts.map +1 -1
  197. package/dist/fix-history.js +15 -0
  198. package/dist/fix-history.js.map +1 -1
  199. package/dist/formatters/sarif.d.ts +3 -0
  200. package/dist/formatters/sarif.d.ts.map +1 -1
  201. package/dist/formatters/sarif.js +36 -12
  202. package/dist/formatters/sarif.js.map +1 -1
  203. package/dist/github-app.d.ts +16 -1
  204. package/dist/github-app.d.ts.map +1 -1
  205. package/dist/github-app.js +85 -2
  206. package/dist/github-app.js.map +1 -1
  207. package/dist/index.js +5 -0
  208. package/dist/index.js.map +1 -1
  209. package/dist/judge-registry.d.ts +157 -0
  210. package/dist/judge-registry.d.ts.map +1 -0
  211. package/dist/judge-registry.js +273 -0
  212. package/dist/judge-registry.js.map +1 -0
  213. package/dist/judges/accessibility.d.ts.map +1 -1
  214. package/dist/judges/accessibility.js +4 -0
  215. package/dist/judges/accessibility.js.map +1 -1
  216. package/dist/judges/agent-instructions.d.ts.map +1 -1
  217. package/dist/judges/agent-instructions.js +4 -0
  218. package/dist/judges/agent-instructions.js.map +1 -1
  219. package/dist/judges/ai-code-safety.d.ts.map +1 -1
  220. package/dist/judges/ai-code-safety.js +4 -0
  221. package/dist/judges/ai-code-safety.js.map +1 -1
  222. package/dist/judges/api-contract.d.ts.map +1 -1
  223. package/dist/judges/api-contract.js +4 -0
  224. package/dist/judges/api-contract.js.map +1 -1
  225. package/dist/judges/api-design.d.ts.map +1 -1
  226. package/dist/judges/api-design.js +4 -0
  227. package/dist/judges/api-design.js.map +1 -1
  228. package/dist/judges/authentication.d.ts.map +1 -1
  229. package/dist/judges/authentication.js +4 -0
  230. package/dist/judges/authentication.js.map +1 -1
  231. package/dist/judges/backwards-compatibility.d.ts.map +1 -1
  232. package/dist/judges/backwards-compatibility.js +4 -0
  233. package/dist/judges/backwards-compatibility.js.map +1 -1
  234. package/dist/judges/caching.d.ts.map +1 -1
  235. package/dist/judges/caching.js +4 -0
  236. package/dist/judges/caching.js.map +1 -1
  237. package/dist/judges/ci-cd.d.ts.map +1 -1
  238. package/dist/judges/ci-cd.js +4 -0
  239. package/dist/judges/ci-cd.js.map +1 -1
  240. package/dist/judges/cloud-readiness.d.ts.map +1 -1
  241. package/dist/judges/cloud-readiness.js +4 -0
  242. package/dist/judges/cloud-readiness.js.map +1 -1
  243. package/dist/judges/code-structure.d.ts.map +1 -1
  244. package/dist/judges/code-structure.js +4 -0
  245. package/dist/judges/code-structure.js.map +1 -1
  246. package/dist/judges/compliance.d.ts.map +1 -1
  247. package/dist/judges/compliance.js +4 -0
  248. package/dist/judges/compliance.js.map +1 -1
  249. package/dist/judges/concurrency.d.ts.map +1 -1
  250. package/dist/judges/concurrency.js +4 -0
  251. package/dist/judges/concurrency.js.map +1 -1
  252. package/dist/judges/configuration-management.d.ts.map +1 -1
  253. package/dist/judges/configuration-management.js +4 -0
  254. package/dist/judges/configuration-management.js.map +1 -1
  255. package/dist/judges/cost-effectiveness.d.ts.map +1 -1
  256. package/dist/judges/cost-effectiveness.js +4 -0
  257. package/dist/judges/cost-effectiveness.js.map +1 -1
  258. package/dist/judges/cybersecurity.d.ts.map +1 -1
  259. package/dist/judges/cybersecurity.js +4 -0
  260. package/dist/judges/cybersecurity.js.map +1 -1
  261. package/dist/judges/data-security.d.ts.map +1 -1
  262. package/dist/judges/data-security.js +4 -0
  263. package/dist/judges/data-security.js.map +1 -1
  264. package/dist/judges/data-sovereignty.d.ts.map +1 -1
  265. package/dist/judges/data-sovereignty.js +4 -0
  266. package/dist/judges/data-sovereignty.js.map +1 -1
  267. package/dist/judges/database.d.ts.map +1 -1
  268. package/dist/judges/database.js +4 -0
  269. package/dist/judges/database.js.map +1 -1
  270. package/dist/judges/dependency-health.d.ts.map +1 -1
  271. package/dist/judges/dependency-health.js +4 -0
  272. package/dist/judges/dependency-health.js.map +1 -1
  273. package/dist/judges/documentation.d.ts.map +1 -1
  274. package/dist/judges/documentation.js +4 -0
  275. package/dist/judges/documentation.js.map +1 -1
  276. package/dist/judges/error-handling.d.ts.map +1 -1
  277. package/dist/judges/error-handling.js +4 -0
  278. package/dist/judges/error-handling.js.map +1 -1
  279. package/dist/judges/ethics-bias.d.ts.map +1 -1
  280. package/dist/judges/ethics-bias.js +4 -0
  281. package/dist/judges/ethics-bias.js.map +1 -1
  282. package/dist/judges/false-positive-review.d.ts.map +1 -1
  283. package/dist/judges/false-positive-review.js +2 -0
  284. package/dist/judges/false-positive-review.js.map +1 -1
  285. package/dist/judges/framework-safety.d.ts.map +1 -1
  286. package/dist/judges/framework-safety.js +4 -0
  287. package/dist/judges/framework-safety.js.map +1 -1
  288. package/dist/judges/hallucination-detection.d.ts.map +1 -1
  289. package/dist/judges/hallucination-detection.js +4 -0
  290. package/dist/judges/hallucination-detection.js.map +1 -1
  291. package/dist/judges/iac-security.d.ts.map +1 -1
  292. package/dist/judges/iac-security.js +4 -0
  293. package/dist/judges/iac-security.js.map +1 -1
  294. package/dist/judges/index.d.ts +59 -0
  295. package/dist/judges/index.d.ts.map +1 -1
  296. package/dist/judges/index.js +65 -189
  297. package/dist/judges/index.js.map +1 -1
  298. package/dist/judges/intent-alignment.d.ts.map +1 -1
  299. package/dist/judges/intent-alignment.js +4 -0
  300. package/dist/judges/intent-alignment.js.map +1 -1
  301. package/dist/judges/internationalization.d.ts.map +1 -1
  302. package/dist/judges/internationalization.js +4 -0
  303. package/dist/judges/internationalization.js.map +1 -1
  304. package/dist/judges/logging-privacy.d.ts.map +1 -1
  305. package/dist/judges/logging-privacy.js +4 -0
  306. package/dist/judges/logging-privacy.js.map +1 -1
  307. package/dist/judges/logic-review.d.ts.map +1 -1
  308. package/dist/judges/logic-review.js +4 -0
  309. package/dist/judges/logic-review.js.map +1 -1
  310. package/dist/judges/maintainability.d.ts.map +1 -1
  311. package/dist/judges/maintainability.js +4 -0
  312. package/dist/judges/maintainability.js.map +1 -1
  313. package/dist/judges/model-fingerprint.d.ts.map +1 -1
  314. package/dist/judges/model-fingerprint.js +4 -0
  315. package/dist/judges/model-fingerprint.js.map +1 -1
  316. package/dist/judges/multi-turn-coherence.d.ts.map +1 -1
  317. package/dist/judges/multi-turn-coherence.js +4 -0
  318. package/dist/judges/multi-turn-coherence.js.map +1 -1
  319. package/dist/judges/observability.d.ts.map +1 -1
  320. package/dist/judges/observability.js +4 -0
  321. package/dist/judges/observability.js.map +1 -1
  322. package/dist/judges/over-engineering.d.ts.map +1 -1
  323. package/dist/judges/over-engineering.js +4 -0
  324. package/dist/judges/over-engineering.js.map +1 -1
  325. package/dist/judges/performance.d.ts.map +1 -1
  326. package/dist/judges/performance.js +4 -0
  327. package/dist/judges/performance.js.map +1 -1
  328. package/dist/judges/portability.d.ts.map +1 -1
  329. package/dist/judges/portability.js +4 -0
  330. package/dist/judges/portability.js.map +1 -1
  331. package/dist/judges/rate-limiting.d.ts.map +1 -1
  332. package/dist/judges/rate-limiting.js +4 -0
  333. package/dist/judges/rate-limiting.js.map +1 -1
  334. package/dist/judges/reliability.d.ts.map +1 -1
  335. package/dist/judges/reliability.js +4 -0
  336. package/dist/judges/reliability.js.map +1 -1
  337. package/dist/judges/scalability.d.ts.map +1 -1
  338. package/dist/judges/scalability.js +4 -0
  339. package/dist/judges/scalability.js.map +1 -1
  340. package/dist/judges/security.d.ts.map +1 -1
  341. package/dist/judges/security.js +4 -0
  342. package/dist/judges/security.js.map +1 -1
  343. package/dist/judges/software-practices.d.ts.map +1 -1
  344. package/dist/judges/software-practices.js +4 -0
  345. package/dist/judges/software-practices.js.map +1 -1
  346. package/dist/judges/testing.d.ts.map +1 -1
  347. package/dist/judges/testing.js +4 -0
  348. package/dist/judges/testing.js.map +1 -1
  349. package/dist/judges/ux.d.ts.map +1 -1
  350. package/dist/judges/ux.js +4 -0
  351. package/dist/judges/ux.js.map +1 -1
  352. package/dist/parallel.d.ts +53 -0
  353. package/dist/parallel.d.ts.map +1 -0
  354. package/dist/parallel.js +170 -0
  355. package/dist/parallel.js.map +1 -0
  356. package/dist/plugins.d.ts +8 -51
  357. package/dist/plugins.d.ts.map +1 -1
  358. package/dist/plugins.js +16 -125
  359. package/dist/plugins.js.map +1 -1
  360. package/dist/security-ids.d.ts +24 -0
  361. package/dist/security-ids.d.ts.map +1 -0
  362. package/dist/security-ids.js +240 -0
  363. package/dist/security-ids.js.map +1 -0
  364. package/dist/tools/prompts.d.ts +4 -0
  365. package/dist/tools/prompts.d.ts.map +1 -1
  366. package/dist/tools/prompts.js +6 -4
  367. package/dist/tools/prompts.js.map +1 -1
  368. package/dist/tools/register-scaffold.d.ts +3 -0
  369. package/dist/tools/register-scaffold.d.ts.map +1 -0
  370. package/dist/tools/register-scaffold.js +399 -0
  371. package/dist/tools/register-scaffold.js.map +1 -0
  372. package/dist/tools/register.d.ts +1 -1
  373. package/dist/tools/register.d.ts.map +1 -1
  374. package/dist/tools/register.js +3 -1
  375. package/dist/tools/register.js.map +1 -1
  376. package/dist/types.d.ts +75 -0
  377. package/dist/types.d.ts.map +1 -1
  378. package/package.json +3 -2
  379. package/server.json +2 -2
@@ -0,0 +1,242 @@
1
+ /**
2
+ * `judges metrics` — Local-only ROI metrics.
3
+ *
4
+ * Computes time-saved, defect-catch, and adoption statistics from
5
+ * local finding lifecycle data and feedback stores. No data leaves
6
+ * the developer's machine.
7
+ *
8
+ * Usage:
9
+ * judges metrics # summary to stdout
10
+ * judges metrics --format json # machine-readable
11
+ * judges metrics --since 30d # last 30 days
12
+ */
13
+ import { existsSync, readFileSync } from "fs";
14
+ import { resolve } from "path";
15
+ // ─── Time Estimates ─────────────────────────────────────────────────────────
16
+ // Conservative estimates for manual review time saved per finding category.
17
+ // Based on industry averages for manual code review discovery.
18
+ const MINUTES_PER_FINDING = {
19
+ critical: 120, // Critical vulns take ~2 hours to discover manually
20
+ high: 60, // High-severity issues ~1 hour
21
+ medium: 30, // Medium issues ~30 minutes
22
+ low: 15, // Low issues ~15 minutes
23
+ info: 5, // Informational ~5 minutes
24
+ };
25
+ const MINUTES_PER_AUTOFIX = 20; // Each auto-fix saves ~20 min of manual patching
26
+ // ─── Data Loading ───────────────────────────────────────────────────────────
27
+ function loadFindingStore(dir) {
28
+ const storePath = resolve(dir, ".judges-findings.json");
29
+ if (!existsSync(storePath))
30
+ return undefined;
31
+ try {
32
+ const raw = JSON.parse(readFileSync(storePath, "utf-8"));
33
+ return raw;
34
+ }
35
+ catch {
36
+ return undefined;
37
+ }
38
+ }
39
+ function _loadFeedbackEntries(dir) {
40
+ const feedbackPath = resolve(dir, ".judges-feedback.json");
41
+ if (!existsSync(feedbackPath))
42
+ return [];
43
+ try {
44
+ const raw = JSON.parse(readFileSync(feedbackPath, "utf-8"));
45
+ return (raw.entries ?? []);
46
+ }
47
+ catch {
48
+ return [];
49
+ }
50
+ }
51
+ // ─── Metrics Computation ────────────────────────────────────────────────────
52
+ function parseSinceDays(since) {
53
+ if (!since)
54
+ return undefined;
55
+ const m = /^(\d+)d$/.exec(since);
56
+ return m ? parseInt(m[1], 10) : undefined;
57
+ }
58
+ function isWithinPeriod(timestamp, cutoff) {
59
+ if (!cutoff)
60
+ return true;
61
+ return new Date(timestamp) >= cutoff;
62
+ }
63
+ export function computeMetrics(dir, sinceDays) {
64
+ const store = loadFindingStore(dir);
65
+ const findings = store?.findings ?? [];
66
+ const now = new Date();
67
+ const cutoff = sinceDays ? new Date(now.getTime() - sinceDays * 86400000) : undefined;
68
+ // Filter by period
69
+ const relevant = cutoff
70
+ ? findings.filter((f) => isWithinPeriod(f.lastSeen, cutoff) || isWithinPeriod(f.firstSeen, cutoff))
71
+ : findings;
72
+ const from = cutoff?.toISOString() ??
73
+ (relevant.length > 0
74
+ ? relevant.reduce((a, b) => (a.firstSeen < b.firstSeen ? a : b)).firstSeen
75
+ : now.toISOString());
76
+ const to = now.toISOString();
77
+ // Categorize
78
+ const fixed = relevant.filter((f) => f.status === "fixed");
79
+ const open = relevant.filter((f) => f.status === "open");
80
+ const acceptedRisk = relevant.filter((f) => f.status === "accepted-risk" || f.status === "wont-fix" || f.status === "deferred");
81
+ const falsePositive = relevant.filter((f) => f.status === "false-positive");
82
+ // By severity
83
+ const bySeverity = {};
84
+ for (const f of relevant) {
85
+ if (!bySeverity[f.severity])
86
+ bySeverity[f.severity] = { detected: 0, fixed: 0 };
87
+ bySeverity[f.severity].detected++;
88
+ if (f.status === "fixed")
89
+ bySeverity[f.severity].fixed++;
90
+ }
91
+ // Auto-fix estimates: findings with fixes available approximate to findings with patches
92
+ // We count findings that were fixed quickly (< 1 day from first seen) as likely auto-fixed
93
+ const quickFixes = fixed.filter((f) => {
94
+ if (!f.fixedAt)
95
+ return false;
96
+ const openDuration = new Date(f.fixedAt).getTime() - new Date(f.firstSeen).getTime();
97
+ return openDuration < 86400000; // Fixed within 24 hours
98
+ });
99
+ // Time saved breakdown
100
+ const breakdown = [];
101
+ for (const sev of ["critical", "high", "medium", "low", "info"]) {
102
+ const count = bySeverity[sev]?.detected ?? 0;
103
+ if (count > 0) {
104
+ breakdown.push({
105
+ category: `${sev} findings detected`,
106
+ count,
107
+ minutesPerItem: MINUTES_PER_FINDING[sev],
108
+ totalMinutes: count * MINUTES_PER_FINDING[sev],
109
+ });
110
+ }
111
+ }
112
+ if (quickFixes.length > 0) {
113
+ breakdown.push({
114
+ category: "Auto-fixes applied",
115
+ count: quickFixes.length,
116
+ minutesPerItem: MINUTES_PER_AUTOFIX,
117
+ totalMinutes: quickFixes.length * MINUTES_PER_AUTOFIX,
118
+ });
119
+ }
120
+ const totalMinutes = breakdown.reduce((sum, b) => sum + b.totalMinutes, 0);
121
+ // Trend: compare first half vs second half of findings by firstSeen
122
+ const sorted = [...relevant].sort((a, b) => a.firstSeen.localeCompare(b.firstSeen));
123
+ const mid = Math.floor(sorted.length / 2);
124
+ const firstHalfOpen = sorted.slice(0, mid).filter((f) => f.status === "open").length;
125
+ const secondHalfOpen = sorted.slice(mid).filter((f) => f.status === "open").length;
126
+ const trend = sorted.length < 4
127
+ ? "stable"
128
+ : secondHalfOpen < firstHalfOpen * 0.8
129
+ ? "improving"
130
+ : secondHalfOpen > firstHalfOpen * 1.2
131
+ ? "degrading"
132
+ : "stable";
133
+ const runCount = store?.runNumber ?? 1;
134
+ return {
135
+ period: { from, to },
136
+ findings: {
137
+ totalDetected: relevant.length,
138
+ totalFixed: fixed.length,
139
+ totalOpen: open.length,
140
+ totalAcceptedRisk: acceptedRisk.length,
141
+ totalFalsePositive: falsePositive.length,
142
+ fixRate: relevant.length > 0 ? fixed.length / relevant.length : 0,
143
+ bySeverity,
144
+ },
145
+ autoFix: {
146
+ available: relevant.length, // All findings potentially have fixes
147
+ applied: quickFixes.length,
148
+ adoptionRate: relevant.length > 0 ? quickFixes.length / relevant.length : 0,
149
+ },
150
+ timeSaved: {
151
+ estimatedMinutes: totalMinutes,
152
+ estimatedHours: Math.round((totalMinutes / 60) * 10) / 10,
153
+ breakdown,
154
+ },
155
+ trend: {
156
+ direction: trend,
157
+ newFindingsPerRun: runCount > 0 ? relevant.length / runCount : 0,
158
+ fixedFindingsPerRun: runCount > 0 ? fixed.length / runCount : 0,
159
+ },
160
+ };
161
+ }
162
+ // ─── Formatters ─────────────────────────────────────────────────────────────
163
+ function formatMetricsText(m) {
164
+ const lines = [
165
+ "╔══════════════════════════════════════════════════════════════╗",
166
+ "║ Judges — ROI Metrics (Local Only) ║",
167
+ "╚══════════════════════════════════════════════════════════════╝",
168
+ "",
169
+ `Period: ${m.period.from.slice(0, 10)} → ${m.period.to.slice(0, 10)}`,
170
+ "",
171
+ "── Findings ────────────────────────────────────────────────────",
172
+ ` Detected: ${m.findings.totalDetected}`,
173
+ ` Fixed: ${m.findings.totalFixed}`,
174
+ ` Open: ${m.findings.totalOpen}`,
175
+ ` Accepted risk: ${m.findings.totalAcceptedRisk}`,
176
+ ` False positive: ${m.findings.totalFalsePositive}`,
177
+ ` Fix rate: ${(m.findings.fixRate * 100).toFixed(1)}%`,
178
+ "",
179
+ ];
180
+ if (Object.keys(m.findings.bySeverity).length > 0) {
181
+ lines.push(" By severity:");
182
+ for (const [sev, s] of Object.entries(m.findings.bySeverity)) {
183
+ lines.push(` ${sev.padEnd(10)} ${s.detected} detected, ${s.fixed} fixed`);
184
+ }
185
+ lines.push("");
186
+ }
187
+ lines.push("── Time Saved (estimated) ──────────────────────────────────");
188
+ lines.push(` Total: ~${m.timeSaved.estimatedHours} hours`);
189
+ for (const b of m.timeSaved.breakdown) {
190
+ lines.push(` ${b.category}: ${b.count} × ${b.minutesPerItem}min = ${b.totalMinutes}min`);
191
+ }
192
+ lines.push("");
193
+ lines.push("── Trend ───────────────────────────────────────────────────");
194
+ const arrow = m.trend.direction === "improving" ? "↗" : m.trend.direction === "degrading" ? "↘" : "→";
195
+ lines.push(` Direction: ${arrow} ${m.trend.direction}`);
196
+ lines.push(` Findings/run: ${m.trend.newFindingsPerRun.toFixed(1)}`);
197
+ lines.push(` Fixed/run: ${m.trend.fixedFindingsPerRun.toFixed(1)}`);
198
+ lines.push("");
199
+ return lines.join("\n");
200
+ }
201
+ // ─── CLI Entry ──────────────────────────────────────────────────────────────
202
+ export function runMetrics(argv) {
203
+ let format = "text";
204
+ let since;
205
+ let dir = ".";
206
+ for (let i = 0; i < argv.length; i++) {
207
+ const arg = argv[i];
208
+ if (arg === "--format" && argv[i + 1])
209
+ format = argv[++i];
210
+ else if (arg === "--since" && argv[i + 1])
211
+ since = argv[++i];
212
+ else if (arg === "--dir" && argv[i + 1])
213
+ dir = argv[++i];
214
+ else if (arg === "--help" || arg === "-h") {
215
+ console.log(`
216
+ judges metrics — Local-only ROI metrics
217
+
218
+ Usage:
219
+ judges metrics Summary to stdout
220
+ judges metrics --format json Machine-readable output
221
+ judges metrics --since 30d Last 30 days only
222
+ judges metrics --dir ./project Target project directory
223
+
224
+ Options:
225
+ --format <fmt> Output format: text (default), json
226
+ --since <days> Time window, e.g. 30d, 90d
227
+ --dir <path> Project directory (default: cwd)
228
+ -h, --help Show this help
229
+ `);
230
+ process.exit(0);
231
+ }
232
+ }
233
+ const sinceDays = parseSinceDays(since);
234
+ const metrics = computeMetrics(resolve(dir), sinceDays);
235
+ if (format === "json") {
236
+ console.log(JSON.stringify(metrics, null, 2));
237
+ }
238
+ else {
239
+ console.log(formatMetricsText(metrics));
240
+ }
241
+ }
242
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/commands/metrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `judges monorepo` — Monorepo workspace evaluation.
3
+ *
4
+ * Discovers packages in a monorepo (lerna, pnpm-workspace, turbo, packages/,
5
+ * apps/) and evaluates each one with its local `.judgesrc` cascading config.
6
+ *
7
+ * Usage:
8
+ * judges monorepo # Auto-detect and evaluate all packages
9
+ * judges monorepo --list # List detected packages only
10
+ * judges monorepo --concurrency 4 # Evaluate 4 packages in parallel
11
+ * judges monorepo --format json # JSON summary
12
+ */
13
+ import type { JudgesConfig } from "../types.js";
14
+ export interface MonorepoPackage {
15
+ /** Package name (from package.json name or directory name) */
16
+ name: string;
17
+ /** Absolute path to the package */
18
+ path: string;
19
+ /** Relative path from root */
20
+ relativePath: string;
21
+ /** Has its own .judgesrc */
22
+ hasLocalConfig: boolean;
23
+ /** Resolved config (cascading merge) */
24
+ config: JudgesConfig;
25
+ /** Languages detected */
26
+ languages: string[];
27
+ }
28
+ export interface MonorepoScanResult {
29
+ /** Root directory */
30
+ root: string;
31
+ /** Monorepo tool detected */
32
+ tool: "pnpm" | "lerna" | "turbo" | "nx" | "npm-workspaces" | "heuristic";
33
+ /** Discovered packages */
34
+ packages: MonorepoPackage[];
35
+ }
36
+ export declare function discoverPackages(root: string): MonorepoScanResult;
37
+ export declare function runMonorepoCommand(argv: string[]): void;
38
+ //# sourceMappingURL=monorepo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monorepo.d.ts","sourceRoot":"","sources":["../../src/commands/monorepo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,cAAc,EAAE,OAAO,CAAC;IACxB,wCAAwC;IACxC,MAAM,EAAE,YAAY,CAAC;IACrB,yBAAyB;IACzB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,IAAI,GAAG,gBAAgB,GAAG,WAAW,CAAC;IACzE,0BAA0B;IAC1B,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAqGD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CA2EjE;AAID,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA6DvD"}
@@ -0,0 +1,233 @@
1
+ /**
2
+ * `judges monorepo` — Monorepo workspace evaluation.
3
+ *
4
+ * Discovers packages in a monorepo (lerna, pnpm-workspace, turbo, packages/,
5
+ * apps/) and evaluates each one with its local `.judgesrc` cascading config.
6
+ *
7
+ * Usage:
8
+ * judges monorepo # Auto-detect and evaluate all packages
9
+ * judges monorepo --list # List detected packages only
10
+ * judges monorepo --concurrency 4 # Evaluate 4 packages in parallel
11
+ * judges monorepo --format json # JSON summary
12
+ */
13
+ import { existsSync, readdirSync, readFileSync, statSync } from "fs";
14
+ import { resolve, join, relative, basename } from "path";
15
+ import { loadCascadingConfig } from "../config.js";
16
+ // ─── Package Discovery ─────────────────────────────────────────────────────
17
+ function readJsonSafe(filepath) {
18
+ try {
19
+ return JSON.parse(readFileSync(filepath, "utf-8"));
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ }
25
+ function readYamlWorkspaces(filepath) {
26
+ try {
27
+ const content = readFileSync(filepath, "utf-8");
28
+ const patterns = [];
29
+ // Simple extraction — lines starting with " - " under "packages:"
30
+ let inPackages = false;
31
+ for (const line of content.split("\n")) {
32
+ if (/^packages:/i.test(line.trim())) {
33
+ inPackages = true;
34
+ continue;
35
+ }
36
+ if (inPackages && line.match(/^\s+-\s+/)) {
37
+ patterns.push(line
38
+ .replace(/^\s+-\s+/, "")
39
+ .replace(/['"]/g, "")
40
+ .trim());
41
+ }
42
+ else if (inPackages && !line.match(/^\s/)) {
43
+ inPackages = false;
44
+ }
45
+ }
46
+ return patterns;
47
+ }
48
+ catch {
49
+ return [];
50
+ }
51
+ }
52
+ function expandGlobDirs(root, patterns) {
53
+ const dirs = [];
54
+ for (const pattern of patterns) {
55
+ const clean = pattern.replace(/\/\*$/, "").replace(/\*\*$/, "");
56
+ const base = join(root, clean);
57
+ if (!existsSync(base) || !statSync(base).isDirectory())
58
+ continue;
59
+ // If pattern ends with * — list subdirectories
60
+ if (pattern.endsWith("/*") || pattern.endsWith("/**")) {
61
+ try {
62
+ for (const entry of readdirSync(base)) {
63
+ const full = join(base, entry);
64
+ if (statSync(full).isDirectory())
65
+ dirs.push(full);
66
+ }
67
+ }
68
+ catch {
69
+ /* skip */
70
+ }
71
+ }
72
+ else {
73
+ dirs.push(base);
74
+ }
75
+ }
76
+ return dirs;
77
+ }
78
+ function detectLanguagesInDir(dir) {
79
+ const langs = new Set();
80
+ const EXT_MAP = {
81
+ ".ts": "typescript",
82
+ ".tsx": "typescript",
83
+ ".js": "javascript",
84
+ ".jsx": "javascript",
85
+ ".mjs": "javascript",
86
+ ".py": "python",
87
+ ".go": "go",
88
+ ".rs": "rust",
89
+ ".java": "java",
90
+ ".cs": "csharp",
91
+ ".rb": "ruby",
92
+ ".php": "php",
93
+ ".swift": "swift",
94
+ ".kt": "kotlin",
95
+ ".cpp": "cpp",
96
+ ".cc": "cpp",
97
+ ".hpp": "cpp",
98
+ ".c": "c",
99
+ ".h": "c",
100
+ };
101
+ try {
102
+ const entries = readdirSync(dir, { recursive: true, withFileTypes: false });
103
+ for (const entry of entries.slice(0, 500)) {
104
+ const ext = entry.substring(entry.lastIndexOf(".")).toLowerCase();
105
+ if (EXT_MAP[ext])
106
+ langs.add(EXT_MAP[ext]);
107
+ }
108
+ }
109
+ catch {
110
+ /* skip */
111
+ }
112
+ return [...langs];
113
+ }
114
+ export function discoverPackages(root) {
115
+ const absRoot = resolve(root);
116
+ let tool = "heuristic";
117
+ let packageDirs = [];
118
+ // 1. pnpm-workspace.yaml
119
+ const pnpmWs = join(absRoot, "pnpm-workspace.yaml");
120
+ if (existsSync(pnpmWs)) {
121
+ tool = "pnpm";
122
+ const patterns = readYamlWorkspaces(pnpmWs);
123
+ packageDirs = expandGlobDirs(absRoot, patterns);
124
+ }
125
+ // 2. lerna.json
126
+ if (packageDirs.length === 0) {
127
+ const lernaPath = join(absRoot, "lerna.json");
128
+ if (existsSync(lernaPath)) {
129
+ tool = "lerna";
130
+ const lerna = readJsonSafe(lernaPath);
131
+ const patterns = lerna?.packages || ["packages/*"];
132
+ packageDirs = expandGlobDirs(absRoot, patterns);
133
+ }
134
+ }
135
+ // 3. turbo.json — check root package.json workspaces
136
+ if (packageDirs.length === 0 && existsSync(join(absRoot, "turbo.json"))) {
137
+ tool = "turbo";
138
+ const rootPkg = readJsonSafe(join(absRoot, "package.json"));
139
+ const workspaces = rootPkg?.workspaces || [];
140
+ packageDirs = expandGlobDirs(absRoot, workspaces.length > 0 ? workspaces : ["packages/*", "apps/*"]);
141
+ }
142
+ // 4. npm workspaces (package.json "workspaces" field)
143
+ if (packageDirs.length === 0) {
144
+ const rootPkg = readJsonSafe(join(absRoot, "package.json"));
145
+ if (rootPkg?.workspaces) {
146
+ tool = "npm-workspaces";
147
+ const workspaces = Array.isArray(rootPkg.workspaces)
148
+ ? rootPkg.workspaces
149
+ : rootPkg.workspaces.packages || [];
150
+ packageDirs = expandGlobDirs(absRoot, workspaces);
151
+ }
152
+ }
153
+ // 5. nx.json
154
+ if (packageDirs.length === 0 && existsSync(join(absRoot, "nx.json"))) {
155
+ tool = "nx";
156
+ packageDirs = expandGlobDirs(absRoot, ["packages/*", "apps/*", "libs/*"]);
157
+ }
158
+ // 6. Heuristic — look for packages/ and apps/ directories
159
+ if (packageDirs.length === 0) {
160
+ packageDirs = expandGlobDirs(absRoot, ["packages/*", "apps/*"]);
161
+ }
162
+ // Build package metadata
163
+ const packages = packageDirs
164
+ .filter((dir) => existsSync(dir) && statSync(dir).isDirectory())
165
+ .map((dir) => {
166
+ const pkg = readJsonSafe(join(dir, "package.json"));
167
+ const hasLocalConfig = existsSync(join(dir, ".judgesrc"));
168
+ const config = loadCascadingConfig(dir, absRoot);
169
+ const name = pkg?.name || basename(dir);
170
+ return {
171
+ name,
172
+ path: dir,
173
+ relativePath: relative(absRoot, dir),
174
+ hasLocalConfig,
175
+ config,
176
+ languages: detectLanguagesInDir(dir),
177
+ };
178
+ });
179
+ return { root: absRoot, tool, packages };
180
+ }
181
+ // ─── CLI Runner ─────────────────────────────────────────────────────────────
182
+ export function runMonorepoCommand(argv) {
183
+ if (argv.includes("--help") || argv.includes("-h")) {
184
+ console.log(`
185
+ judges monorepo — Monorepo workspace evaluation
186
+
187
+ Usage:
188
+ judges monorepo [root] Auto-detect and list packages
189
+ judges monorepo --list List detected packages only
190
+ judges monorepo --format json JSON output
191
+
192
+ Supports:
193
+ • pnpm-workspace.yaml
194
+ • lerna.json
195
+ • turbo.json
196
+ • npm workspaces (package.json "workspaces")
197
+ • nx.json
198
+ • Heuristic (packages/, apps/ directories)
199
+
200
+ Each package inherits its .judgesrc config via cascading config resolution.
201
+
202
+ Options:
203
+ --list List packages only (no evaluation)
204
+ --format <fmt> Output format: text, json
205
+ --help, -h Show this help
206
+ `);
207
+ return;
208
+ }
209
+ const root = argv.find((a, i) => i > 1 && !a.startsWith("-") && argv[i - 1] !== "--format") || ".";
210
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
211
+ console.log(`\n Scanning for monorepo packages in ${resolve(root)}...\n`);
212
+ const result = discoverPackages(resolve(root));
213
+ if (format === "json") {
214
+ console.log(JSON.stringify(result, null, 2));
215
+ return;
216
+ }
217
+ // Text output
218
+ console.log(` Monorepo tool: ${result.tool}`);
219
+ console.log(` Packages found: ${result.packages.length}\n`);
220
+ if (result.packages.length === 0) {
221
+ console.log(" No packages detected. Run from a monorepo root or use manual package paths.\n");
222
+ return;
223
+ }
224
+ const nameWidth = Math.max(12, ...result.packages.map((p) => p.name.length));
225
+ console.log(` ${"PACKAGE".padEnd(nameWidth)} ${"PATH".padEnd(30)} ${"CONFIG"} LANGUAGES`);
226
+ console.log(` ${"─".repeat(nameWidth)} ${"─".repeat(30)} ${"──────"} ${"─".repeat(20)}`);
227
+ for (const pkg of result.packages) {
228
+ const configStatus = pkg.hasLocalConfig ? "local " : "inherit";
229
+ console.log(` ${pkg.name.padEnd(nameWidth)} ${pkg.relativePath.padEnd(30)} ${configStatus} ${pkg.languages.join(", ") || "—"}`);
230
+ }
231
+ console.log("");
232
+ }
233
+ //# sourceMappingURL=monorepo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monorepo.js","sourceRoot":"","sources":["../../src/commands/monorepo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * `judges notify` — Webhook notification system for findings alerts.
3
+ *
4
+ * Sends evaluation results to configured webhook endpoints (Slack, Teams,
5
+ * generic HTTP). Users configure their own endpoints — Judges never stores
6
+ * or processes data on behalf of users.
7
+ *
8
+ * Usage:
9
+ * judges notify --file results.json --channel slack # Send to Slack
10
+ * judges notify --file results.json --channel teams # Send to Teams
11
+ * judges notify --file results.json --channel webhook # Generic webhook
12
+ * judges eval src/app.ts --notify # Evaluate + notify
13
+ *
14
+ * Configuration in .judgesrc:
15
+ * ```json
16
+ * {
17
+ * "notifications": {
18
+ * "channels": [
19
+ * { "type": "slack", "url": "https://hooks.slack.com/..." },
20
+ * { "type": "teams", "url": "https://outlook.office.com/webhook/..." },
21
+ * { "type": "webhook", "url": "https://my-server.com/judges-hook",
22
+ * "headers": { "Authorization": "Bearer ..." } }
23
+ * ],
24
+ * "minSeverity": "medium",
25
+ * "onlyOnFailure": false
26
+ * }
27
+ * }
28
+ * ```
29
+ */
30
+ import type { Finding, Severity, TribunalVerdict } from "../types.js";
31
+ export type NotificationChannelType = "slack" | "teams" | "webhook";
32
+ export interface NotificationChannel {
33
+ /** Channel type */
34
+ type: NotificationChannelType;
35
+ /** Webhook URL — provided and hosted by the user */
36
+ url: string;
37
+ /** Optional custom headers (e.g. auth tokens) */
38
+ headers?: Record<string, string>;
39
+ /** Optional display name for this channel */
40
+ name?: string;
41
+ }
42
+ export interface NotificationConfig {
43
+ /** Channels to send notifications to */
44
+ channels: NotificationChannel[];
45
+ /** Only notify for findings at or above this severity */
46
+ minSeverity?: Severity;
47
+ /** Only send when the verdict is "fail" */
48
+ onlyOnFailure?: boolean;
49
+ }
50
+ export interface NotificationPayload {
51
+ /** Project or file being evaluated */
52
+ target: string;
53
+ /** Overall verdict */
54
+ verdict: "pass" | "fail" | "warning";
55
+ /** Aggregate score (0-10) */
56
+ score: number;
57
+ /** Summary counts by severity */
58
+ summary: Record<Severity, number>;
59
+ /** Total finding count */
60
+ totalFindings: number;
61
+ /** Top findings (limited to 10 for brevity) */
62
+ topFindings: Array<{
63
+ ruleId: string;
64
+ severity: Severity;
65
+ title: string;
66
+ line?: number;
67
+ }>;
68
+ /** Timestamp of evaluation */
69
+ timestamp: string;
70
+ }
71
+ export declare function buildNotificationPayload(target: string, verdict: TribunalVerdict, filteredFindings: Finding[]): NotificationPayload;
72
+ export declare function sendNotification(channel: NotificationChannel, payload: NotificationPayload): Promise<{
73
+ success: boolean;
74
+ error?: string;
75
+ }>;
76
+ export declare function notifyAllChannels(config: NotificationConfig, target: string, verdict: TribunalVerdict): Promise<void>;
77
+ export declare function parseNotificationConfig(obj: Record<string, unknown>): NotificationConfig | undefined;
78
+ export declare function runNotify(argv: string[]): Promise<void>;
79
+ //# sourceMappingURL=notify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../src/commands/notify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAItE,MAAM,MAAM,uBAAuB,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;AAEpE,MAAM,WAAW,mBAAmB;IAClC,mBAAmB;IACnB,IAAI,EAAE,uBAAuB,CAAC;IAC9B,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAC;IACZ,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,wCAAwC;IACxC,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,yDAAyD;IACzD,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,2CAA2C;IAC3C,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACrC,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAClC,0BAA0B;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,WAAW,EAAE,KAAK,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,QAAQ,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;IACH,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAaD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,eAAe,EACxB,gBAAgB,EAAE,OAAO,EAAE,GAC1B,mBAAmB,CAyBrB;AA6FD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,mBAAmB,EAC5B,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAgC/C;AAID,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CAkCf;AAMD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,kBAAkB,GAAG,SAAS,CAmCpG;AAID,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyF7D"}