ppef 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (336) hide show
  1. package/README.md +172 -0
  2. package/bin/ppef.mjs +20 -0
  3. package/dist/__tests__/framework-pipeline.integration.test.d.ts +7 -0
  4. package/dist/__tests__/framework-pipeline.integration.test.d.ts.map +1 -0
  5. package/dist/__tests__/framework-pipeline.integration.test.js +415 -0
  6. package/dist/__tests__/framework-pipeline.integration.test.js.map +1 -0
  7. package/dist/__tests__/index-exports.unit.test.d.ts +8 -0
  8. package/dist/__tests__/index-exports.unit.test.d.ts.map +1 -0
  9. package/dist/__tests__/index-exports.unit.test.js +127 -0
  10. package/dist/__tests__/index-exports.unit.test.js.map +1 -0
  11. package/dist/__tests__/registry-executor.integration.test.d.ts +5 -0
  12. package/dist/__tests__/registry-executor.integration.test.d.ts.map +1 -0
  13. package/dist/__tests__/registry-executor.integration.test.js +352 -0
  14. package/dist/__tests__/registry-executor.integration.test.js.map +1 -0
  15. package/dist/__tests__/test-helpers.d.ts +94 -0
  16. package/dist/__tests__/test-helpers.d.ts.map +1 -0
  17. package/dist/__tests__/test-helpers.js +271 -0
  18. package/dist/__tests__/test-helpers.js.map +1 -0
  19. package/dist/aggregation/__tests__/aggregators.unit.test.d.ts +7 -0
  20. package/dist/aggregation/__tests__/aggregators.unit.test.d.ts.map +1 -0
  21. package/dist/aggregation/__tests__/aggregators.unit.test.js +350 -0
  22. package/dist/aggregation/__tests__/aggregators.unit.test.js.map +1 -0
  23. package/dist/aggregation/__tests__/pipeline.unit.test.d.ts +7 -0
  24. package/dist/aggregation/__tests__/pipeline.unit.test.d.ts.map +1 -0
  25. package/dist/aggregation/__tests__/pipeline.unit.test.js +213 -0
  26. package/dist/aggregation/__tests__/pipeline.unit.test.js.map +1 -0
  27. package/dist/aggregation/aggregators.d.ts +63 -0
  28. package/dist/aggregation/aggregators.d.ts.map +1 -0
  29. package/dist/aggregation/aggregators.js +228 -0
  30. package/dist/aggregation/aggregators.js.map +1 -0
  31. package/dist/aggregation/index.d.ts +8 -0
  32. package/dist/aggregation/index.d.ts.map +1 -0
  33. package/dist/aggregation/index.js +8 -0
  34. package/dist/aggregation/index.js.map +1 -0
  35. package/dist/aggregation/pipeline.d.ts +38 -0
  36. package/dist/aggregation/pipeline.d.ts.map +1 -0
  37. package/dist/aggregation/pipeline.js +198 -0
  38. package/dist/aggregation/pipeline.js.map +1 -0
  39. package/dist/claims/__tests__/evaluator.unit.test.d.ts +12 -0
  40. package/dist/claims/__tests__/evaluator.unit.test.d.ts.map +1 -0
  41. package/dist/claims/__tests__/evaluator.unit.test.js +801 -0
  42. package/dist/claims/__tests__/evaluator.unit.test.js.map +1 -0
  43. package/dist/claims/evaluator.d.ts +33 -0
  44. package/dist/claims/evaluator.d.ts.map +1 -0
  45. package/dist/claims/evaluator.js +174 -0
  46. package/dist/claims/evaluator.js.map +1 -0
  47. package/dist/claims/index.d.ts +7 -0
  48. package/dist/claims/index.d.ts.map +1 -0
  49. package/dist/claims/index.js +7 -0
  50. package/dist/claims/index.js.map +1 -0
  51. package/dist/cli/__tests__/aggregate.command.unit.test.d.ts +7 -0
  52. package/dist/cli/__tests__/aggregate.command.unit.test.d.ts.map +1 -0
  53. package/dist/cli/__tests__/aggregate.command.unit.test.js +396 -0
  54. package/dist/cli/__tests__/aggregate.command.unit.test.js.map +1 -0
  55. package/dist/cli/__tests__/commands.unit.test.d.ts +10 -0
  56. package/dist/cli/__tests__/commands.unit.test.d.ts.map +1 -0
  57. package/dist/cli/__tests__/commands.unit.test.js +217 -0
  58. package/dist/cli/__tests__/commands.unit.test.js.map +1 -0
  59. package/dist/cli/__tests__/index.unit.test.d.ts +10 -0
  60. package/dist/cli/__tests__/index.unit.test.d.ts.map +1 -0
  61. package/dist/cli/__tests__/index.unit.test.js +65 -0
  62. package/dist/cli/__tests__/index.unit.test.js.map +1 -0
  63. package/dist/cli/__tests__/logger.unit.test.d.ts +11 -0
  64. package/dist/cli/__tests__/logger.unit.test.d.ts.map +1 -0
  65. package/dist/cli/__tests__/logger.unit.test.js +180 -0
  66. package/dist/cli/__tests__/logger.unit.test.js.map +1 -0
  67. package/dist/cli/__tests__/module-loader.unit.test.d.ts +11 -0
  68. package/dist/cli/__tests__/module-loader.unit.test.d.ts.map +1 -0
  69. package/dist/cli/__tests__/module-loader.unit.test.js +262 -0
  70. package/dist/cli/__tests__/module-loader.unit.test.js.map +1 -0
  71. package/dist/cli/__tests__/output-writer.unit.test.d.ts +10 -0
  72. package/dist/cli/__tests__/output-writer.unit.test.d.ts.map +1 -0
  73. package/dist/cli/__tests__/output-writer.unit.test.js +216 -0
  74. package/dist/cli/__tests__/output-writer.unit.test.js.map +1 -0
  75. package/dist/cli/__tests__/plan.command.unit.test.d.ts +7 -0
  76. package/dist/cli/__tests__/plan.command.unit.test.d.ts.map +1 -0
  77. package/dist/cli/__tests__/plan.command.unit.test.js +289 -0
  78. package/dist/cli/__tests__/plan.command.unit.test.js.map +1 -0
  79. package/dist/cli/__tests__/run.command.unit.test.d.ts +7 -0
  80. package/dist/cli/__tests__/run.command.unit.test.d.ts.map +1 -0
  81. package/dist/cli/__tests__/run.command.unit.test.js +422 -0
  82. package/dist/cli/__tests__/run.command.unit.test.js.map +1 -0
  83. package/dist/cli/__tests__/validate.command.unit.test.d.ts +7 -0
  84. package/dist/cli/__tests__/validate.command.unit.test.d.ts.map +1 -0
  85. package/dist/cli/__tests__/validate.command.unit.test.js +226 -0
  86. package/dist/cli/__tests__/validate.command.unit.test.js.map +1 -0
  87. package/dist/cli/command-deps.d.ts +125 -0
  88. package/dist/cli/command-deps.d.ts.map +1 -0
  89. package/dist/cli/command-deps.js +7 -0
  90. package/dist/cli/command-deps.js.map +1 -0
  91. package/dist/cli/commands/aggregate.d.ts +35 -0
  92. package/dist/cli/commands/aggregate.d.ts.map +1 -0
  93. package/dist/cli/commands/aggregate.js +121 -0
  94. package/dist/cli/commands/aggregate.js.map +1 -0
  95. package/dist/cli/commands/plan.d.ts +36 -0
  96. package/dist/cli/commands/plan.d.ts.map +1 -0
  97. package/dist/cli/commands/plan.js +109 -0
  98. package/dist/cli/commands/plan.js.map +1 -0
  99. package/dist/cli/commands/run.d.ts +33 -0
  100. package/dist/cli/commands/run.d.ts.map +1 -0
  101. package/dist/cli/commands/run.js +185 -0
  102. package/dist/cli/commands/run.js.map +1 -0
  103. package/dist/cli/commands/validate.d.ts +27 -0
  104. package/dist/cli/commands/validate.d.ts.map +1 -0
  105. package/dist/cli/commands/validate.js +88 -0
  106. package/dist/cli/commands/validate.js.map +1 -0
  107. package/dist/cli/config-loader.d.ts +30 -0
  108. package/dist/cli/config-loader.d.ts.map +1 -0
  109. package/dist/cli/config-loader.js +181 -0
  110. package/dist/cli/config-loader.js.map +1 -0
  111. package/dist/cli/index.d.ts +26 -0
  112. package/dist/cli/index.d.ts.map +1 -0
  113. package/dist/cli/index.js +58 -0
  114. package/dist/cli/index.js.map +1 -0
  115. package/dist/cli/logger.d.ts +75 -0
  116. package/dist/cli/logger.d.ts.map +1 -0
  117. package/dist/cli/logger.js +131 -0
  118. package/dist/cli/logger.js.map +1 -0
  119. package/dist/cli/module-loader.d.ts +46 -0
  120. package/dist/cli/module-loader.d.ts.map +1 -0
  121. package/dist/cli/module-loader.js +116 -0
  122. package/dist/cli/module-loader.js.map +1 -0
  123. package/dist/cli/output-writer.d.ts +51 -0
  124. package/dist/cli/output-writer.d.ts.map +1 -0
  125. package/dist/cli/output-writer.js +65 -0
  126. package/dist/cli/output-writer.js.map +1 -0
  127. package/dist/cli/types.d.ts +174 -0
  128. package/dist/cli/types.d.ts.map +1 -0
  129. package/dist/cli/types.js +7 -0
  130. package/dist/cli/types.js.map +1 -0
  131. package/dist/collector/__tests__/result-collector.unit.test.d.ts +7 -0
  132. package/dist/collector/__tests__/result-collector.unit.test.d.ts.map +1 -0
  133. package/dist/collector/__tests__/result-collector.unit.test.js +1021 -0
  134. package/dist/collector/__tests__/result-collector.unit.test.js.map +1 -0
  135. package/dist/collector/__tests__/schema.unit.test.d.ts +7 -0
  136. package/dist/collector/__tests__/schema.unit.test.d.ts.map +1 -0
  137. package/dist/collector/__tests__/schema.unit.test.js +360 -0
  138. package/dist/collector/__tests__/schema.unit.test.js.map +1 -0
  139. package/dist/collector/index.d.ts +8 -0
  140. package/dist/collector/index.d.ts.map +1 -0
  141. package/dist/collector/index.js +8 -0
  142. package/dist/collector/index.js.map +1 -0
  143. package/dist/collector/result-collector.d.ts +159 -0
  144. package/dist/collector/result-collector.d.ts.map +1 -0
  145. package/dist/collector/result-collector.js +213 -0
  146. package/dist/collector/result-collector.js.map +1 -0
  147. package/dist/collector/schema.d.ts +34 -0
  148. package/dist/collector/schema.d.ts.map +1 -0
  149. package/dist/collector/schema.js +145 -0
  150. package/dist/collector/schema.js.map +1 -0
  151. package/dist/executor/__tests__/checkpoint-hash-bug.diagnostic.test.d.ts +10 -0
  152. package/dist/executor/__tests__/checkpoint-hash-bug.diagnostic.test.d.ts.map +1 -0
  153. package/dist/executor/__tests__/checkpoint-hash-bug.diagnostic.test.js +122 -0
  154. package/dist/executor/__tests__/checkpoint-hash-bug.diagnostic.test.js.map +1 -0
  155. package/dist/executor/__tests__/checkpoint-manager.integration.test.d.ts +7 -0
  156. package/dist/executor/__tests__/checkpoint-manager.integration.test.d.ts.map +1 -0
  157. package/dist/executor/__tests__/checkpoint-manager.integration.test.js +330 -0
  158. package/dist/executor/__tests__/checkpoint-manager.integration.test.js.map +1 -0
  159. package/dist/executor/__tests__/checkpoint-manager.unit.test.d.ts +7 -0
  160. package/dist/executor/__tests__/checkpoint-manager.unit.test.d.ts.map +1 -0
  161. package/dist/executor/__tests__/checkpoint-manager.unit.test.js +531 -0
  162. package/dist/executor/__tests__/checkpoint-manager.unit.test.js.map +1 -0
  163. package/dist/executor/__tests__/checkpoint-merge-bug.diagnostic.test.d.ts +8 -0
  164. package/dist/executor/__tests__/checkpoint-merge-bug.diagnostic.test.d.ts.map +1 -0
  165. package/dist/executor/__tests__/checkpoint-merge-bug.diagnostic.test.js +493 -0
  166. package/dist/executor/__tests__/checkpoint-merge-bug.diagnostic.test.js.map +1 -0
  167. package/dist/executor/__tests__/checkpoint-merge-bug.unit.test.d.ts +8 -0
  168. package/dist/executor/__tests__/checkpoint-merge-bug.unit.test.d.ts.map +1 -0
  169. package/dist/executor/__tests__/checkpoint-merge-bug.unit.test.js +164 -0
  170. package/dist/executor/__tests__/checkpoint-merge-bug.unit.test.js.map +1 -0
  171. package/dist/executor/__tests__/checkpoint-storage.unit.test.d.ts +7 -0
  172. package/dist/executor/__tests__/checkpoint-storage.unit.test.d.ts.map +1 -0
  173. package/dist/executor/__tests__/checkpoint-storage.unit.test.js +490 -0
  174. package/dist/executor/__tests__/checkpoint-storage.unit.test.js.map +1 -0
  175. package/dist/executor/__tests__/executor.unit.test.d.ts +7 -0
  176. package/dist/executor/__tests__/executor.unit.test.d.ts.map +1 -0
  177. package/dist/executor/__tests__/executor.unit.test.js +202 -0
  178. package/dist/executor/__tests__/executor.unit.test.js.map +1 -0
  179. package/dist/executor/__tests__/memory-monitor.unit.test.d.ts +7 -0
  180. package/dist/executor/__tests__/memory-monitor.unit.test.d.ts.map +1 -0
  181. package/dist/executor/__tests__/memory-monitor.unit.test.js +285 -0
  182. package/dist/executor/__tests__/memory-monitor.unit.test.js.map +1 -0
  183. package/dist/executor/__tests__/parallel-checkpoint-merge.integration.test.d.ts +12 -0
  184. package/dist/executor/__tests__/parallel-checkpoint-merge.integration.test.d.ts.map +1 -0
  185. package/dist/executor/__tests__/parallel-checkpoint-merge.integration.test.js +196 -0
  186. package/dist/executor/__tests__/parallel-checkpoint-merge.integration.test.js.map +1 -0
  187. package/dist/executor/__tests__/parallel-executor.integration.test.d.ts +7 -0
  188. package/dist/executor/__tests__/parallel-executor.integration.test.d.ts.map +1 -0
  189. package/dist/executor/__tests__/parallel-executor.integration.test.js +249 -0
  190. package/dist/executor/__tests__/parallel-executor.integration.test.js.map +1 -0
  191. package/dist/executor/__tests__/parallel-executor.unit.test.d.ts +8 -0
  192. package/dist/executor/__tests__/parallel-executor.unit.test.d.ts.map +1 -0
  193. package/dist/executor/__tests__/parallel-executor.unit.test.js +473 -0
  194. package/dist/executor/__tests__/parallel-executor.unit.test.js.map +1 -0
  195. package/dist/executor/__tests__/run-id.unit.test.d.ts +8 -0
  196. package/dist/executor/__tests__/run-id.unit.test.d.ts.map +1 -0
  197. package/dist/executor/__tests__/run-id.unit.test.js +156 -0
  198. package/dist/executor/__tests__/run-id.unit.test.js.map +1 -0
  199. package/dist/executor/__tests__/worker-entry.integration.test.d.ts +24 -0
  200. package/dist/executor/__tests__/worker-entry.integration.test.d.ts.map +1 -0
  201. package/dist/executor/__tests__/worker-entry.integration.test.js +82 -0
  202. package/dist/executor/__tests__/worker-entry.integration.test.js.map +1 -0
  203. package/dist/executor/__tests__/worker-entry.unit.test.d.ts +7 -0
  204. package/dist/executor/__tests__/worker-entry.unit.test.d.ts.map +1 -0
  205. package/dist/executor/__tests__/worker-entry.unit.test.js +364 -0
  206. package/dist/executor/__tests__/worker-entry.unit.test.js.map +1 -0
  207. package/dist/executor/checkpoint-manager.d.ts +231 -0
  208. package/dist/executor/checkpoint-manager.d.ts.map +1 -0
  209. package/dist/executor/checkpoint-manager.js +395 -0
  210. package/dist/executor/checkpoint-manager.js.map +1 -0
  211. package/dist/executor/checkpoint-storage.d.ts +230 -0
  212. package/dist/executor/checkpoint-storage.d.ts.map +1 -0
  213. package/dist/executor/checkpoint-storage.js +370 -0
  214. package/dist/executor/checkpoint-storage.js.map +1 -0
  215. package/dist/executor/checkpoint-types.d.ts +48 -0
  216. package/dist/executor/checkpoint-types.d.ts.map +1 -0
  217. package/dist/executor/checkpoint-types.js +8 -0
  218. package/dist/executor/checkpoint-types.js.map +1 -0
  219. package/dist/executor/executor.d.ts +164 -0
  220. package/dist/executor/executor.d.ts.map +1 -0
  221. package/dist/executor/executor.js +408 -0
  222. package/dist/executor/executor.js.map +1 -0
  223. package/dist/executor/index.d.ts +11 -0
  224. package/dist/executor/index.d.ts.map +1 -0
  225. package/dist/executor/index.js +11 -0
  226. package/dist/executor/index.js.map +1 -0
  227. package/dist/executor/memory-monitor.d.ts +115 -0
  228. package/dist/executor/memory-monitor.d.ts.map +1 -0
  229. package/dist/executor/memory-monitor.js +168 -0
  230. package/dist/executor/memory-monitor.js.map +1 -0
  231. package/dist/executor/parallel-executor.d.ts +239 -0
  232. package/dist/executor/parallel-executor.d.ts.map +1 -0
  233. package/dist/executor/parallel-executor.js +329 -0
  234. package/dist/executor/parallel-executor.js.map +1 -0
  235. package/dist/executor/run-id.d.ts +71 -0
  236. package/dist/executor/run-id.d.ts.map +1 -0
  237. package/dist/executor/run-id.js +74 -0
  238. package/dist/executor/run-id.js.map +1 -0
  239. package/dist/executor/worker-entry.d.ts +10 -0
  240. package/dist/executor/worker-entry.d.ts.map +1 -0
  241. package/dist/executor/worker-entry.js +42 -0
  242. package/dist/executor/worker-entry.js.map +1 -0
  243. package/dist/executor/worker-executor.d.ts +156 -0
  244. package/dist/executor/worker-executor.d.ts.map +1 -0
  245. package/dist/executor/worker-executor.js +88 -0
  246. package/dist/executor/worker-executor.js.map +1 -0
  247. package/dist/index.cjs +11 -0
  248. package/dist/index.d.ts +15 -0
  249. package/dist/index.d.ts.map +1 -0
  250. package/dist/index.js +24 -0
  251. package/dist/index.js.map +1 -0
  252. package/dist/registry/case-registry.d.ts +113 -0
  253. package/dist/registry/case-registry.d.ts.map +1 -0
  254. package/dist/registry/case-registry.js +160 -0
  255. package/dist/registry/case-registry.js.map +1 -0
  256. package/dist/registry/index.d.ts +8 -0
  257. package/dist/registry/index.d.ts.map +1 -0
  258. package/dist/registry/index.js +8 -0
  259. package/dist/registry/index.js.map +1 -0
  260. package/dist/registry/sut-registry.d.ts +96 -0
  261. package/dist/registry/sut-registry.d.ts.map +1 -0
  262. package/dist/registry/sut-registry.js +126 -0
  263. package/dist/registry/sut-registry.js.map +1 -0
  264. package/dist/renderers/index.d.ts +10 -0
  265. package/dist/renderers/index.d.ts.map +1 -0
  266. package/dist/renderers/index.js +9 -0
  267. package/dist/renderers/index.js.map +1 -0
  268. package/dist/renderers/latex-renderer.d.ts +84 -0
  269. package/dist/renderers/latex-renderer.d.ts.map +1 -0
  270. package/dist/renderers/latex-renderer.js +208 -0
  271. package/dist/renderers/latex-renderer.js.map +1 -0
  272. package/dist/renderers/types.d.ts +106 -0
  273. package/dist/renderers/types.d.ts.map +1 -0
  274. package/dist/renderers/types.js +23 -0
  275. package/dist/renderers/types.js.map +1 -0
  276. package/dist/robustness/__tests__/analyzer.unit.test.d.ts +11 -0
  277. package/dist/robustness/__tests__/analyzer.unit.test.d.ts.map +1 -0
  278. package/dist/robustness/__tests__/analyzer.unit.test.js +455 -0
  279. package/dist/robustness/__tests__/analyzer.unit.test.js.map +1 -0
  280. package/dist/robustness/__tests__/perturbations.unit.test.d.ts +11 -0
  281. package/dist/robustness/__tests__/perturbations.unit.test.d.ts.map +1 -0
  282. package/dist/robustness/__tests__/perturbations.unit.test.js +284 -0
  283. package/dist/robustness/__tests__/perturbations.unit.test.js.map +1 -0
  284. package/dist/robustness/analyzer.d.ts +61 -0
  285. package/dist/robustness/analyzer.d.ts.map +1 -0
  286. package/dist/robustness/analyzer.js +191 -0
  287. package/dist/robustness/analyzer.js.map +1 -0
  288. package/dist/robustness/index.d.ts +8 -0
  289. package/dist/robustness/index.d.ts.map +1 -0
  290. package/dist/robustness/index.js +8 -0
  291. package/dist/robustness/index.js.map +1 -0
  292. package/dist/robustness/perturbations.d.ts +46 -0
  293. package/dist/robustness/perturbations.d.ts.map +1 -0
  294. package/dist/robustness/perturbations.js +184 -0
  295. package/dist/robustness/perturbations.js.map +1 -0
  296. package/dist/statistical/__tests__/mann-whitney-u.unit.test.d.ts +7 -0
  297. package/dist/statistical/__tests__/mann-whitney-u.unit.test.d.ts.map +1 -0
  298. package/dist/statistical/__tests__/mann-whitney-u.unit.test.js +185 -0
  299. package/dist/statistical/__tests__/mann-whitney-u.unit.test.js.map +1 -0
  300. package/dist/statistical/index.d.ts +8 -0
  301. package/dist/statistical/index.d.ts.map +1 -0
  302. package/dist/statistical/index.js +8 -0
  303. package/dist/statistical/index.js.map +1 -0
  304. package/dist/statistical/mann-whitney-u.d.ts +62 -0
  305. package/dist/statistical/mann-whitney-u.d.ts.map +1 -0
  306. package/dist/statistical/mann-whitney-u.js +127 -0
  307. package/dist/statistical/mann-whitney-u.js.map +1 -0
  308. package/dist/types/aggregate.d.ts +124 -0
  309. package/dist/types/aggregate.d.ts.map +1 -0
  310. package/dist/types/aggregate.js +9 -0
  311. package/dist/types/aggregate.js.map +1 -0
  312. package/dist/types/case.d.ts +105 -0
  313. package/dist/types/case.d.ts.map +1 -0
  314. package/dist/types/case.js +10 -0
  315. package/dist/types/case.js.map +1 -0
  316. package/dist/types/claims.d.ts +122 -0
  317. package/dist/types/claims.d.ts.map +1 -0
  318. package/dist/types/claims.js +14 -0
  319. package/dist/types/claims.js.map +1 -0
  320. package/dist/types/index.d.ts +12 -0
  321. package/dist/types/index.d.ts.map +1 -0
  322. package/dist/types/index.js +7 -0
  323. package/dist/types/index.js.map +1 -0
  324. package/dist/types/perturbation.d.ts +105 -0
  325. package/dist/types/perturbation.d.ts.map +1 -0
  326. package/dist/types/perturbation.js +9 -0
  327. package/dist/types/perturbation.js.map +1 -0
  328. package/dist/types/result.d.ts +150 -0
  329. package/dist/types/result.d.ts.map +1 -0
  330. package/dist/types/result.js +12 -0
  331. package/dist/types/result.js.map +1 -0
  332. package/dist/types/sut.d.ts +128 -0
  333. package/dist/types/sut.d.ts.map +1 -0
  334. package/dist/types/sut.js +12 -0
  335. package/dist/types/sut.js.map +1 -0
  336. package/package.json +290 -7
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Config Loader
3
+ *
4
+ * Loads and validates experiment configuration from JSON files.
5
+ */
6
+ import { readFile } from "node:fs/promises";
7
+ import { resolve, dirname } from "node:path";
8
+ /**
9
+ * Load and parse experiment configuration from a JSON file.
10
+ *
11
+ * @param configPath - Path to config file (can be absolute or relative)
12
+ * @returns Loaded configuration with base directory
13
+ * @throws Error if file cannot be read or parsed
14
+ */
15
+ export async function loadConfig(configPath) {
16
+ // Resolve absolute path
17
+ const absolutePath = resolve(configPath);
18
+ // Read and parse JSON
19
+ const content = await readFile(absolutePath, "utf-8");
20
+ const config = JSON.parse(content);
21
+ // Get base directory (for resolving module paths)
22
+ const baseDir = dirname(absolutePath);
23
+ return {
24
+ config,
25
+ baseDir,
26
+ configPath: absolutePath,
27
+ };
28
+ }
29
+ /**
30
+ * Validate experiment configuration.
31
+ *
32
+ * @param config - Configuration to validate
33
+ * @returns Validation result with errors and warnings
34
+ */
35
+ export function validateConfig(config) {
36
+ const errors = [];
37
+ const warnings = [];
38
+ // Validate experiment metadata
39
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
40
+ if (!config.experiment?.name) {
41
+ errors.push("experiment.name is required");
42
+ }
43
+ // Validate executor config
44
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
45
+ if (!config.executor) {
46
+ errors.push("executor configuration is required");
47
+ }
48
+ else {
49
+ if (config.executor.repetitions !== undefined && config.executor.repetitions < 1) {
50
+ errors.push("executor.repetitions must be at least 1");
51
+ }
52
+ if (config.executor.seedBase !== undefined && config.executor.seedBase < 0) {
53
+ errors.push("executor.seedBase must be non-negative");
54
+ }
55
+ if (config.executor.timeoutMs !== undefined && config.executor.timeoutMs < 0) {
56
+ errors.push("executor.timeoutMs must be non-negative");
57
+ }
58
+ if (config.executor.concurrency !== undefined && config.executor.concurrency < 1) {
59
+ errors.push("executor.concurrency must be at least 1");
60
+ }
61
+ }
62
+ // Validate SUTs
63
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
64
+ if (!config.suts || config.suts.length === 0) {
65
+ warnings.push("No SUTs configured - experiment will have nothing to execute");
66
+ }
67
+ else {
68
+ for (let i = 0; i < config.suts.length; i++) {
69
+ const sut = config.suts[i];
70
+ if (!sut.id) {
71
+ errors.push(`suts[${i}].id is required`);
72
+ }
73
+ if (!sut.module) {
74
+ errors.push(`suts[${i}].module is required`);
75
+ }
76
+ if (!sut.exportName) {
77
+ errors.push(`suts[${i}].exportName is required`);
78
+ }
79
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
80
+ if (!sut.registration?.name) {
81
+ errors.push(`suts[${i}].registration.name is required`);
82
+ }
83
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
84
+ if (!sut.registration?.version) {
85
+ errors.push(`suts[${i}].registration.version is required`);
86
+ }
87
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
88
+ if (!sut.registration?.role) {
89
+ errors.push(`suts[${i}].registration.role is required`);
90
+ }
91
+ else if (!["primary", "baseline", "oracle"].includes(sut.registration.role)) {
92
+ errors.push(`suts[${i}].registration.role must be one of: primary, baseline, oracle`);
93
+ }
94
+ }
95
+ // Check for duplicate SUT IDs
96
+ const sutIds = new Set();
97
+ for (const sut of config.suts) {
98
+ if (sut.id && sutIds.has(sut.id)) {
99
+ errors.push(`Duplicate SUT ID: ${sut.id}`);
100
+ }
101
+ sutIds.add(sut.id);
102
+ }
103
+ }
104
+ // Validate cases
105
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
106
+ if (!config.cases || config.cases.length === 0) {
107
+ warnings.push("No cases configured - experiment will have nothing to execute");
108
+ }
109
+ else {
110
+ for (let i = 0; i < config.cases.length; i++) {
111
+ const testCase = config.cases[i];
112
+ if (!testCase.id) {
113
+ errors.push(`cases[${i}].id is required`);
114
+ }
115
+ if (!testCase.module) {
116
+ errors.push(`cases[${i}].module is required`);
117
+ }
118
+ if (!testCase.exportName) {
119
+ errors.push(`cases[${i}].exportName is required`);
120
+ }
121
+ }
122
+ // Check for duplicate case IDs
123
+ const caseIds = new Set();
124
+ for (const testCase of config.cases) {
125
+ if (testCase.id && caseIds.has(testCase.id)) {
126
+ errors.push(`Duplicate case ID: ${testCase.id}`);
127
+ }
128
+ caseIds.add(testCase.id);
129
+ }
130
+ }
131
+ // Validate metrics extractor
132
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
133
+ if (!config.metricsExtractor) {
134
+ errors.push("metricsExtractor configuration is required");
135
+ }
136
+ else {
137
+ if (!config.metricsExtractor.module) {
138
+ errors.push("metricsExtractor.module is required");
139
+ }
140
+ if (!config.metricsExtractor.exportName) {
141
+ errors.push("metricsExtractor.exportName is required");
142
+ }
143
+ }
144
+ // Validate output config
145
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
146
+ if (!config.output) {
147
+ warnings.push("No output configuration specified - using defaults");
148
+ }
149
+ else {
150
+ if (config.output.format && !["json", "json-pretty"].includes(config.output.format)) {
151
+ errors.push('output.format must be one of: "json", "json-pretty"');
152
+ }
153
+ }
154
+ return {
155
+ valid: errors.length === 0,
156
+ errors,
157
+ warnings,
158
+ };
159
+ }
160
+ /**
161
+ * Load and validate experiment configuration.
162
+ *
163
+ * @param configPath - Path to config file
164
+ * @returns Loaded and validated configuration
165
+ * @throws Error if validation fails
166
+ */
167
+ export async function loadAndValidateConfig(configPath) {
168
+ const loaded = await loadConfig(configPath);
169
+ const validation = validateConfig(loaded.config);
170
+ if (!validation.valid) {
171
+ throw new Error(`Configuration validation failed:\n${validation.errors.map((e) => ` - ${e}`).join("\n")}`);
172
+ }
173
+ // Print warnings if any
174
+ if (validation.warnings.length > 0) {
175
+ for (const warning of validation.warnings) {
176
+ console.warn(`Warning: ${warning}`);
177
+ }
178
+ }
179
+ return loaded;
180
+ }
181
+ //# sourceMappingURL=config-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../../src/cli/config-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * PPEF CLI
3
+ *
4
+ * Command-line interface for the Portable Programmatic Evaluation Framework.
5
+ */
6
+ import { Command } from "commander";
7
+ import { registerAggregateCommand } from "./commands/aggregate.js";
8
+ import { registerPlanCommand } from "./commands/plan.js";
9
+ import { registerRunCommand } from "./commands/run.js";
10
+ import { registerValidateCommand } from "./commands/validate.js";
11
+ /**
12
+ * Create and configure the CLI program.
13
+ *
14
+ * This function is exported for testing purposes.
15
+ *
16
+ * @returns Configured Commander program
17
+ */
18
+ export declare function createCliProgram(): Command;
19
+ /**
20
+ * Run the CLI and return exit code.
21
+ *
22
+ * @returns Exit code (0 for success, 1 for error)
23
+ */
24
+ export declare function runCli(): Promise<number>;
25
+ export { registerAggregateCommand, registerPlanCommand, registerRunCommand, registerValidateCommand, };
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAe1C;AAED;;;;GAIG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAS9C;AAiBD,OAAO,EACN,wBAAwB,EACxB,mBAAmB,EACnB,kBAAkB,EAClB,uBAAuB,GACvB,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * PPEF CLI
3
+ *
4
+ * Command-line interface for the Portable Programmatic Evaluation Framework.
5
+ */
6
+ import { Command } from "commander";
7
+ import { registerAggregateCommand } from "./commands/aggregate.js";
8
+ import { registerPlanCommand } from "./commands/plan.js";
9
+ import { registerRunCommand } from "./commands/run.js";
10
+ import { registerValidateCommand } from "./commands/validate.js";
11
+ /**
12
+ * Create and configure the CLI program.
13
+ *
14
+ * This function is exported for testing purposes.
15
+ *
16
+ * @returns Configured Commander program
17
+ */
18
+ export function createCliProgram() {
19
+ const program = new Command();
20
+ program
21
+ .name("ppef")
22
+ .description("Portable Programmatic Evaluation Framework - CLI for experiment execution")
23
+ .version("1.0.1");
24
+ // Register commands
25
+ registerRunCommand(program);
26
+ registerValidateCommand(program);
27
+ registerPlanCommand(program);
28
+ registerAggregateCommand(program);
29
+ return program;
30
+ }
31
+ /**
32
+ * Run the CLI and return exit code.
33
+ *
34
+ * @returns Exit code (0 for success, 1 for error)
35
+ */
36
+ export async function runCli() {
37
+ const program = createCliProgram();
38
+ try {
39
+ await program.parseAsync(process.argv);
40
+ return 0;
41
+ }
42
+ catch {
43
+ return 1;
44
+ }
45
+ }
46
+ /**
47
+ * Run CLI when executed directly (for development/testing).
48
+ */
49
+ if (import.meta.url === `file://${process.argv[1]}`) {
50
+ runCli().then((code) => {
51
+ process.exit(code);
52
+ }, (error) => {
53
+ console.error("Fatal error:", error);
54
+ process.exit(1);
55
+ });
56
+ }
57
+ export { registerAggregateCommand, registerPlanCommand, registerRunCommand, registerValidateCommand, };
58
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB;IAC/B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACL,IAAI,CAAC,MAAM,CAAC;SACZ,WAAW,CAAC,2EAA2E,CAAC;SACxF,OAAO,CAAC,OAAO,CAAC,CAAC;IAEnB,oBAAoB;IACpB,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC5B,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACjC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAElC,OAAO,OAAO,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM;IAC3B,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;IAEnC,IAAI,CAAC;QACJ,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvC,OAAO,CAAC,CAAC;IACV,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,CAAC,CAAC;IACV,CAAC;AACF,CAAC;AAED;;GAEG;AACH,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,UAAU,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACrD,MAAM,EAAE,CAAC,IAAI,CACZ,CAAC,IAAI,EAAE,EAAE;QACR,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;QACT,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC,CACD,CAAC;AACH,CAAC;AAED,OAAO,EACN,wBAAwB,EACxB,mBAAmB,EACnB,kBAAkB,EAClB,uBAAuB,GACvB,CAAC"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * CLI Logger
3
+ *
4
+ * Handles progress reporting, error messages, and output formatting.
5
+ */
6
+ import type { ExecutionProgress } from "../executor/index.js";
7
+ /**
8
+ * Log level for controlling verbosity.
9
+ */
10
+ export type LogLevel = "silent" | "error" | "warn" | "info" | "debug";
11
+ /**
12
+ * CLI logger for formatted output.
13
+ */
14
+ export declare class CliLogger {
15
+ private readonly level;
16
+ private readonly quiet;
17
+ private showProgress;
18
+ private lastProgress;
19
+ constructor(options: {
20
+ verbose?: boolean;
21
+ quiet?: boolean;
22
+ });
23
+ /**
24
+ * Enable or disable progress bar updates.
25
+ */
26
+ setProgress(enabled: boolean): void;
27
+ /**
28
+ * Log a debug message (only shown in verbose mode).
29
+ */
30
+ debug(message: string): void;
31
+ /**
32
+ * Log an info message.
33
+ */
34
+ info(message: string): void;
35
+ /**
36
+ * Log a warning message.
37
+ */
38
+ warn(message: string): void;
39
+ /**
40
+ * Log an error message (always shown unless quiet).
41
+ */
42
+ error(message: string): void;
43
+ /**
44
+ * Log execution progress.
45
+ */
46
+ progress(progress: ExecutionProgress): void;
47
+ /**
48
+ * Clear the current progress line.
49
+ */
50
+ clearProgress(): void;
51
+ /**
52
+ * Log a header section.
53
+ */
54
+ header(title: string): void;
55
+ /**
56
+ * Log a sub-header.
57
+ */
58
+ subheader(title: string): void;
59
+ /**
60
+ * Create a progress reporter callback for the executor.
61
+ */
62
+ createProgressReporter(): (progress: ExecutionProgress) => void;
63
+ /**
64
+ * Internal log method.
65
+ */
66
+ private log;
67
+ }
68
+ /**
69
+ * Create a default logger instance.
70
+ */
71
+ export declare function createLogger(options?: {
72
+ verbose?: boolean;
73
+ quiet?: boolean;
74
+ }): CliLogger;
75
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/cli/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEtE;;GAEG;AACH,qBAAa,SAAS;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAW;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAU;IAChC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAM;gBAEd,OAAO,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;IAK3D;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAInC;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM5B;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM3B;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM3B;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM5B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IA0B3C;;OAEG;IACH,aAAa,IAAI,IAAI;IAOrB;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAQ3B;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAO9B;;OAEG;IACH,sBAAsB,IAAI,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI;IAM/D;;OAEG;IACH,OAAO,CAAC,GAAG;CAKX;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,SAAS,CAE5F"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * CLI Logger
3
+ *
4
+ * Handles progress reporting, error messages, and output formatting.
5
+ */
6
+ /**
7
+ * CLI logger for formatted output.
8
+ */
9
+ export class CliLogger {
10
+ level;
11
+ quiet;
12
+ showProgress = false;
13
+ lastProgress = "";
14
+ constructor(options) {
15
+ this.quiet = options.quiet ?? false;
16
+ this.level = options.verbose ? "debug" : this.quiet ? "silent" : "info";
17
+ }
18
+ /**
19
+ * Enable or disable progress bar updates.
20
+ */
21
+ setProgress(enabled) {
22
+ this.showProgress = enabled;
23
+ }
24
+ /**
25
+ * Log a debug message (only shown in verbose mode).
26
+ */
27
+ debug(message) {
28
+ if (this.level === "debug") {
29
+ this.log(`[DEBUG] ${message}`);
30
+ }
31
+ }
32
+ /**
33
+ * Log an info message.
34
+ */
35
+ info(message) {
36
+ if (this.level !== "silent") {
37
+ this.log(message);
38
+ }
39
+ }
40
+ /**
41
+ * Log a warning message.
42
+ */
43
+ warn(message) {
44
+ if (this.level !== "silent") {
45
+ this.log(`Warning: ${message}`);
46
+ }
47
+ }
48
+ /**
49
+ * Log an error message (always shown unless quiet).
50
+ */
51
+ error(message) {
52
+ if (this.level !== "silent") {
53
+ this.log(`Error: ${message}`);
54
+ }
55
+ }
56
+ /**
57
+ * Log execution progress.
58
+ */
59
+ progress(progress) {
60
+ if (!this.showProgress || this.level === "silent") {
61
+ return;
62
+ }
63
+ const percentage = Math.round((progress.completed / progress.total) * 100);
64
+ const currentSut = progress.currentSut ?? "unknown";
65
+ const currentCase = progress.currentCase ?? "unknown";
66
+ const currentRep = progress.currentRepetition ?? 0;
67
+ const elapsed = Math.round(progress.elapsedMs / 1000);
68
+ const message = `[${percentage}%] ${currentSut} / ${currentCase} (rep ${currentRep + 1}) - ${elapsed}s`;
69
+ // Only update if message changed (avoid flickering)
70
+ if (message !== this.lastProgress) {
71
+ // Use carriage return to overwrite line
72
+ process.stdout.write(`\r${message.padEnd(80)}`);
73
+ this.lastProgress = message;
74
+ }
75
+ // New line when complete
76
+ if (progress.completed >= progress.total) {
77
+ process.stdout.write("\n");
78
+ }
79
+ }
80
+ /**
81
+ * Clear the current progress line.
82
+ */
83
+ clearProgress() {
84
+ if (this.lastProgress) {
85
+ process.stdout.write("\r" + " ".repeat(80) + "\r");
86
+ this.lastProgress = "";
87
+ }
88
+ }
89
+ /**
90
+ * Log a header section.
91
+ */
92
+ header(title) {
93
+ if (this.level === "silent") {
94
+ return;
95
+ }
96
+ this.log("");
97
+ this.log(`=== ${title} ===`);
98
+ }
99
+ /**
100
+ * Log a sub-header.
101
+ */
102
+ subheader(title) {
103
+ if (this.level === "silent") {
104
+ return;
105
+ }
106
+ this.log(`--- ${title}`);
107
+ }
108
+ /**
109
+ * Create a progress reporter callback for the executor.
110
+ */
111
+ createProgressReporter() {
112
+ return (progress) => {
113
+ this.progress(progress);
114
+ };
115
+ }
116
+ /**
117
+ * Internal log method.
118
+ */
119
+ log(message) {
120
+ // Clear progress line before logging
121
+ this.clearProgress();
122
+ console.log(message);
123
+ }
124
+ }
125
+ /**
126
+ * Create a default logger instance.
127
+ */
128
+ export function createLogger(options = {}) {
129
+ return new CliLogger(options);
130
+ }
131
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/cli/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Module Loader
3
+ *
4
+ * Dynamically loads JavaScript/TypeScript modules containing SUT factories,
5
+ * case definitions, and metrics extractors.
6
+ */
7
+ import type { CaseDefinition, SutDefinition } from "../types/index.js";
8
+ /**
9
+ * Load a SUT factory from a module.
10
+ *
11
+ * @param modulePath - Path to module file
12
+ * @param exportName - Name of the export to use
13
+ * @param baseDir - Base directory for resolving paths
14
+ * @returns SUT definition ready for registration
15
+ * @throws Error if export cannot be found or loaded
16
+ */
17
+ export declare function loadSutFactory(modulePath: string, exportName: string, baseDir: string, registration: {
18
+ id: string;
19
+ name: string;
20
+ version: string;
21
+ role: "primary" | "baseline" | "oracle";
22
+ config: Readonly<Record<string, unknown>>;
23
+ tags: readonly string[];
24
+ description?: string;
25
+ }, config?: Record<string, unknown>): Promise<SutDefinition>;
26
+ /**
27
+ * Load a case definition from a module.
28
+ *
29
+ * @param modulePath - Path to module file
30
+ * @param exportName - Name of the export to use
31
+ * @param baseDir - Base directory for resolving paths
32
+ * @returns Case definition ready for use
33
+ * @throws Error if export cannot be found or loaded
34
+ */
35
+ export declare function loadCaseDefinition(modulePath: string, exportName: string, baseDir: string): Promise<CaseDefinition>;
36
+ /**
37
+ * Load a metrics extractor from a module.
38
+ *
39
+ * @param modulePath - Path to module file
40
+ * @param exportName - Name of the export to use
41
+ * @param baseDir - Base directory for resolving paths
42
+ * @returns Metrics extractor function
43
+ * @throws Error if export cannot be found or loaded
44
+ */
45
+ export declare function loadMetricsExtractor(modulePath: string, exportName: string, baseDir: string): Promise<(result: unknown) => Record<string, number>>;
46
+ //# sourceMappingURL=module-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-loader.d.ts","sourceRoot":"","sources":["../../src/cli/module-loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AA8BvE;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CACnC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;IACxC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1C,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB,EACD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,aAAa,CAAC,CA+BxB;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACvC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,cAAc,CAAC,CAqCzB;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACzC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAYtD"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Module Loader
3
+ *
4
+ * Dynamically loads JavaScript/TypeScript modules containing SUT factories,
5
+ * case definitions, and metrics extractors.
6
+ */
7
+ import { resolve } from "node:path";
8
+ import { pathToFileURL } from "node:url";
9
+ /**
10
+ * Load a module from a file path.
11
+ *
12
+ * @param modulePath - Path to module file (relative to base directory)
13
+ * @param baseDir - Base directory for resolving relative paths
14
+ * @returns Loaded module exports
15
+ * @throws Error if module cannot be loaded
16
+ */
17
+ async function loadModule(modulePath, baseDir) {
18
+ const absolutePath = resolve(baseDir, modulePath);
19
+ // Use import with file:// URL for proper ESM support
20
+ const moduleUrl = pathToFileURL(absolutePath).href;
21
+ try {
22
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
23
+ const module = await import(moduleUrl);
24
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
25
+ return module;
26
+ }
27
+ catch (error) {
28
+ if (error instanceof Error) {
29
+ throw new Error(`Failed to load module from ${modulePath}: ${error.message}`);
30
+ }
31
+ throw error;
32
+ }
33
+ }
34
+ /**
35
+ * Load a SUT factory from a module.
36
+ *
37
+ * @param modulePath - Path to module file
38
+ * @param exportName - Name of the export to use
39
+ * @param baseDir - Base directory for resolving paths
40
+ * @returns SUT definition ready for registration
41
+ * @throws Error if export cannot be found or loaded
42
+ */
43
+ export async function loadSutFactory(modulePath, exportName, baseDir, registration, config) {
44
+ const module = await loadModule(modulePath, baseDir);
45
+ const factoryExport = module[exportName];
46
+ if (typeof factoryExport !== "function") {
47
+ throw new Error(`Export "${exportName}" in ${modulePath} is not a function. ` +
48
+ `Found type: ${typeof factoryExport}`);
49
+ }
50
+ // Wrap the factory to match our expected SutFactory type
51
+ const factory = (userConfig) => {
52
+ const instance = factoryExport({ ...config, ...userConfig });
53
+ const mergedConfig = { ...config, ...userConfig, ...(instance.config ?? {}) };
54
+ return {
55
+ id: registration.id,
56
+ config: mergedConfig,
57
+ run: instance.run,
58
+ };
59
+ };
60
+ return {
61
+ registration,
62
+ factory,
63
+ };
64
+ }
65
+ /**
66
+ * Load a case definition from a module.
67
+ *
68
+ * @param modulePath - Path to module file
69
+ * @param exportName - Name of the export to use
70
+ * @param baseDir - Base directory for resolving paths
71
+ * @returns Case definition ready for use
72
+ * @throws Error if export cannot be found or loaded
73
+ */
74
+ export async function loadCaseDefinition(modulePath, exportName, baseDir) {
75
+ const module = await loadModule(modulePath, baseDir);
76
+ const caseExport = module[exportName];
77
+ if (typeof caseExport !== "function") {
78
+ throw new Error(`Export "${exportName}" in ${modulePath} is not a function. ` +
79
+ `Found type: ${typeof caseExport}`);
80
+ }
81
+ const definition = caseExport();
82
+ // Validate structure
83
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
84
+ if (!definition.case?.caseId) {
85
+ throw new Error(`Export "${exportName}" in ${modulePath} does not return a valid case definition. ` +
86
+ `Missing case.caseId.`);
87
+ }
88
+ if (typeof definition.getInput !== "function") {
89
+ throw new Error(`Export "${exportName}" in ${modulePath} does not return a valid case definition. ` +
90
+ `Missing getInput function.`);
91
+ }
92
+ if (typeof definition.getInputs !== "function") {
93
+ throw new Error(`Export "${exportName}" in ${modulePath} does not return a valid case definition. ` +
94
+ `Missing getInputs function.`);
95
+ }
96
+ return definition;
97
+ }
98
+ /**
99
+ * Load a metrics extractor from a module.
100
+ *
101
+ * @param modulePath - Path to module file
102
+ * @param exportName - Name of the export to use
103
+ * @param baseDir - Base directory for resolving paths
104
+ * @returns Metrics extractor function
105
+ * @throws Error if export cannot be found or loaded
106
+ */
107
+ export async function loadMetricsExtractor(modulePath, exportName, baseDir) {
108
+ const module = await loadModule(modulePath, baseDir);
109
+ const extractorExport = module[exportName];
110
+ if (typeof extractorExport !== "function") {
111
+ throw new Error(`Export "${exportName}" in ${modulePath} is not a function. ` +
112
+ `Found type: ${typeof extractorExport}`);
113
+ }
114
+ return extractorExport;
115
+ }
116
+ //# sourceMappingURL=module-loader.js.map