@opensip-cli/simulation 0.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 (348) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +8 -0
  3. package/README.md +31 -0
  4. package/dist/__tests__/internal-surface.test.d.ts +9 -0
  5. package/dist/__tests__/internal-surface.test.d.ts.map +1 -0
  6. package/dist/__tests__/internal-surface.test.js +38 -0
  7. package/dist/__tests__/internal-surface.test.js.map +1 -0
  8. package/dist/__tests__/plugin-loader.test.d.ts +2 -0
  9. package/dist/__tests__/plugin-loader.test.d.ts.map +1 -0
  10. package/dist/__tests__/plugin-loader.test.js +64 -0
  11. package/dist/__tests__/plugin-loader.test.js.map +1 -0
  12. package/dist/__tests__/public-api.test.d.ts +15 -0
  13. package/dist/__tests__/public-api.test.d.ts.map +1 -0
  14. package/dist/__tests__/public-api.test.js +73 -0
  15. package/dist/__tests__/public-api.test.js.map +1 -0
  16. package/dist/__tests__/registry-cross-kind.test.d.ts +6 -0
  17. package/dist/__tests__/registry-cross-kind.test.d.ts.map +1 -0
  18. package/dist/__tests__/registry-cross-kind.test.js +86 -0
  19. package/dist/__tests__/registry-cross-kind.test.js.map +1 -0
  20. package/dist/__tests__/scenario-execution.test.d.ts +10 -0
  21. package/dist/__tests__/scenario-execution.test.d.ts.map +1 -0
  22. package/dist/__tests__/scenario-execution.test.js +92 -0
  23. package/dist/__tests__/scenario-execution.test.js.map +1 -0
  24. package/dist/__tests__/sim-capability-contract.test.d.ts +10 -0
  25. package/dist/__tests__/sim-capability-contract.test.d.ts.map +1 -0
  26. package/dist/__tests__/sim-capability-contract.test.js +131 -0
  27. package/dist/__tests__/sim-capability-contract.test.js.map +1 -0
  28. package/dist/__tests__/sim-config-schema.test.d.ts +5 -0
  29. package/dist/__tests__/sim-config-schema.test.d.ts.map +1 -0
  30. package/dist/__tests__/sim-config-schema.test.js +23 -0
  31. package/dist/__tests__/sim-config-schema.test.js.map +1 -0
  32. package/dist/__tests__/sim-failure-signal.test.d.ts +10 -0
  33. package/dist/__tests__/sim-failure-signal.test.d.ts.map +1 -0
  34. package/dist/__tests__/sim-failure-signal.test.js +86 -0
  35. package/dist/__tests__/sim-failure-signal.test.js.map +1 -0
  36. package/dist/__tests__/surviving-surface-edges.test.d.ts +10 -0
  37. package/dist/__tests__/surviving-surface-edges.test.d.ts.map +1 -0
  38. package/dist/__tests__/surviving-surface-edges.test.js +122 -0
  39. package/dist/__tests__/surviving-surface-edges.test.js.map +1 -0
  40. package/dist/__tests__/test-utils/targets.d.ts +26 -0
  41. package/dist/__tests__/test-utils/targets.d.ts.map +1 -0
  42. package/dist/__tests__/test-utils/targets.js +38 -0
  43. package/dist/__tests__/test-utils/targets.js.map +1 -0
  44. package/dist/__tests__/test-utils/with-sim-scope.d.ts +12 -0
  45. package/dist/__tests__/test-utils/with-sim-scope.d.ts.map +1 -0
  46. package/dist/__tests__/test-utils/with-sim-scope.js +22 -0
  47. package/dist/__tests__/test-utils/with-sim-scope.js.map +1 -0
  48. package/dist/__tests__/tool-live-view.test.d.ts +20 -0
  49. package/dist/__tests__/tool-live-view.test.d.ts.map +1 -0
  50. package/dist/__tests__/tool-live-view.test.js +146 -0
  51. package/dist/__tests__/tool-live-view.test.js.map +1 -0
  52. package/dist/__tests__/tool-show-mode.test.d.ts +10 -0
  53. package/dist/__tests__/tool-show-mode.test.d.ts.map +1 -0
  54. package/dist/__tests__/tool-show-mode.test.js +156 -0
  55. package/dist/__tests__/tool-show-mode.test.js.map +1 -0
  56. package/dist/__tests__/tool.test.d.ts +15 -0
  57. package/dist/__tests__/tool.test.d.ts.map +1 -0
  58. package/dist/__tests__/tool.test.js +250 -0
  59. package/dist/__tests__/tool.test.js.map +1 -0
  60. package/dist/cli/__tests__/sim-config.test.d.ts +2 -0
  61. package/dist/cli/__tests__/sim-config.test.d.ts.map +1 -0
  62. package/dist/cli/__tests__/sim-config.test.js +94 -0
  63. package/dist/cli/__tests__/sim-config.test.js.map +1 -0
  64. package/dist/cli/__tests__/sim-runner.test.d.ts +23 -0
  65. package/dist/cli/__tests__/sim-runner.test.d.ts.map +1 -0
  66. package/dist/cli/__tests__/sim-runner.test.js +188 -0
  67. package/dist/cli/__tests__/sim-runner.test.js.map +1 -0
  68. package/dist/cli/__tests__/sim-worker.test.d.ts +12 -0
  69. package/dist/cli/__tests__/sim-worker.test.d.ts.map +1 -0
  70. package/dist/cli/__tests__/sim-worker.test.js +69 -0
  71. package/dist/cli/__tests__/sim-worker.test.js.map +1 -0
  72. package/dist/cli/__tests__/sim.test.d.ts +2 -0
  73. package/dist/cli/__tests__/sim.test.d.ts.map +1 -0
  74. package/dist/cli/__tests__/sim.test.js +232 -0
  75. package/dist/cli/__tests__/sim.test.js.map +1 -0
  76. package/dist/cli/sim-config-schema.d.ts +30 -0
  77. package/dist/cli/sim-config-schema.d.ts.map +1 -0
  78. package/dist/cli/sim-config-schema.js +33 -0
  79. package/dist/cli/sim-config-schema.js.map +1 -0
  80. package/dist/cli/sim-config.d.ts +22 -0
  81. package/dist/cli/sim-config.d.ts.map +1 -0
  82. package/dist/cli/sim-config.js +73 -0
  83. package/dist/cli/sim-config.js.map +1 -0
  84. package/dist/cli/sim-runner.d.ts +60 -0
  85. package/dist/cli/sim-runner.d.ts.map +1 -0
  86. package/dist/cli/sim-runner.js +175 -0
  87. package/dist/cli/sim-runner.js.map +1 -0
  88. package/dist/cli/sim-worker.d.ts +24 -0
  89. package/dist/cli/sim-worker.d.ts.map +1 -0
  90. package/dist/cli/sim-worker.js +65 -0
  91. package/dist/cli/sim-worker.js.map +1 -0
  92. package/dist/cli/sim.d.ts +56 -0
  93. package/dist/cli/sim.d.ts.map +1 -0
  94. package/dist/cli/sim.js +265 -0
  95. package/dist/cli/sim.js.map +1 -0
  96. package/dist/framework/__tests__/assertions.test.d.ts +2 -0
  97. package/dist/framework/__tests__/assertions.test.d.ts.map +1 -0
  98. package/dist/framework/__tests__/assertions.test.js +122 -0
  99. package/dist/framework/__tests__/assertions.test.js.map +1 -0
  100. package/dist/framework/__tests__/misc-coverage.test.d.ts +18 -0
  101. package/dist/framework/__tests__/misc-coverage.test.d.ts.map +1 -0
  102. package/dist/framework/__tests__/misc-coverage.test.js +142 -0
  103. package/dist/framework/__tests__/misc-coverage.test.js.map +1 -0
  104. package/dist/framework/__tests__/resolve-metric.test.d.ts +12 -0
  105. package/dist/framework/__tests__/resolve-metric.test.d.ts.map +1 -0
  106. package/dist/framework/__tests__/resolve-metric.test.js +124 -0
  107. package/dist/framework/__tests__/resolve-metric.test.js.map +1 -0
  108. package/dist/framework/__tests__/result-builder.test.d.ts +2 -0
  109. package/dist/framework/__tests__/result-builder.test.d.ts.map +1 -0
  110. package/dist/framework/__tests__/result-builder.test.js +180 -0
  111. package/dist/framework/__tests__/result-builder.test.js.map +1 -0
  112. package/dist/framework/__tests__/scenario-logger.test.d.ts +9 -0
  113. package/dist/framework/__tests__/scenario-logger.test.d.ts.map +1 -0
  114. package/dist/framework/__tests__/scenario-logger.test.js +110 -0
  115. package/dist/framework/__tests__/scenario-logger.test.js.map +1 -0
  116. package/dist/framework/__tests__/validation.test.d.ts +9 -0
  117. package/dist/framework/__tests__/validation.test.d.ts.map +1 -0
  118. package/dist/framework/__tests__/validation.test.js +126 -0
  119. package/dist/framework/__tests__/validation.test.js.map +1 -0
  120. package/dist/framework/assertions.d.ts +106 -0
  121. package/dist/framework/assertions.d.ts.map +1 -0
  122. package/dist/framework/assertions.js +256 -0
  123. package/dist/framework/assertions.js.map +1 -0
  124. package/dist/framework/execution/__tests__/execution-engine.test.d.ts +9 -0
  125. package/dist/framework/execution/__tests__/execution-engine.test.d.ts.map +1 -0
  126. package/dist/framework/execution/__tests__/execution-engine.test.js +138 -0
  127. package/dist/framework/execution/__tests__/execution-engine.test.js.map +1 -0
  128. package/dist/framework/execution/__tests__/fault-builders.test.d.ts +5 -0
  129. package/dist/framework/execution/__tests__/fault-builders.test.d.ts.map +1 -0
  130. package/dist/framework/execution/__tests__/fault-builders.test.js +23 -0
  131. package/dist/framework/execution/__tests__/fault-builders.test.js.map +1 -0
  132. package/dist/framework/execution/__tests__/fault-model.test.d.ts +6 -0
  133. package/dist/framework/execution/__tests__/fault-model.test.d.ts.map +1 -0
  134. package/dist/framework/execution/__tests__/fault-model.test.js +64 -0
  135. package/dist/framework/execution/__tests__/fault-model.test.js.map +1 -0
  136. package/dist/framework/execution/__tests__/http-target.test.d.ts +5 -0
  137. package/dist/framework/execution/__tests__/http-target.test.d.ts.map +1 -0
  138. package/dist/framework/execution/__tests__/http-target.test.js +36 -0
  139. package/dist/framework/execution/__tests__/http-target.test.js.map +1 -0
  140. package/dist/framework/execution/__tests__/run-load-window.test.d.ts +7 -0
  141. package/dist/framework/execution/__tests__/run-load-window.test.d.ts.map +1 -0
  142. package/dist/framework/execution/__tests__/run-load-window.test.js +89 -0
  143. package/dist/framework/execution/__tests__/run-load-window.test.js.map +1 -0
  144. package/dist/framework/execution/execution-engine.d.ts +55 -0
  145. package/dist/framework/execution/execution-engine.d.ts.map +1 -0
  146. package/dist/framework/execution/execution-engine.js +111 -0
  147. package/dist/framework/execution/execution-engine.js.map +1 -0
  148. package/dist/framework/execution/fault-builders.d.ts +26 -0
  149. package/dist/framework/execution/fault-builders.d.ts.map +1 -0
  150. package/dist/framework/execution/fault-builders.js +24 -0
  151. package/dist/framework/execution/fault-builders.js.map +1 -0
  152. package/dist/framework/execution/fault-model.d.ts +49 -0
  153. package/dist/framework/execution/fault-model.d.ts.map +1 -0
  154. package/dist/framework/execution/fault-model.js +108 -0
  155. package/dist/framework/execution/fault-model.js.map +1 -0
  156. package/dist/framework/execution/fault-spec.d.ts +40 -0
  157. package/dist/framework/execution/fault-spec.d.ts.map +1 -0
  158. package/dist/framework/execution/fault-spec.js +23 -0
  159. package/dist/framework/execution/fault-spec.js.map +1 -0
  160. package/dist/framework/execution/http-target.d.ts +34 -0
  161. package/dist/framework/execution/http-target.d.ts.map +1 -0
  162. package/dist/framework/execution/http-target.js +41 -0
  163. package/dist/framework/execution/http-target.js.map +1 -0
  164. package/dist/framework/execution/latency-tracker.d.ts +44 -0
  165. package/dist/framework/execution/latency-tracker.d.ts.map +1 -0
  166. package/dist/framework/execution/latency-tracker.js +76 -0
  167. package/dist/framework/execution/latency-tracker.js.map +1 -0
  168. package/dist/framework/execution/run-load-window.d.ts +45 -0
  169. package/dist/framework/execution/run-load-window.d.ts.map +1 -0
  170. package/dist/framework/execution/run-load-window.js +136 -0
  171. package/dist/framework/execution/run-load-window.js.map +1 -0
  172. package/dist/framework/execution/scenario-aborted-error.d.ts +14 -0
  173. package/dist/framework/execution/scenario-aborted-error.d.ts.map +1 -0
  174. package/dist/framework/execution/scenario-aborted-error.js +24 -0
  175. package/dist/framework/execution/scenario-aborted-error.js.map +1 -0
  176. package/dist/framework/execution/target.d.ts +35 -0
  177. package/dist/framework/execution/target.d.ts.map +1 -0
  178. package/dist/framework/execution/target.js +21 -0
  179. package/dist/framework/execution/target.js.map +1 -0
  180. package/dist/framework/registry.d.ts +67 -0
  181. package/dist/framework/registry.d.ts.map +1 -0
  182. package/dist/framework/registry.js +113 -0
  183. package/dist/framework/registry.js.map +1 -0
  184. package/dist/framework/resolve-metric.d.ts +79 -0
  185. package/dist/framework/resolve-metric.d.ts.map +1 -0
  186. package/dist/framework/resolve-metric.js +135 -0
  187. package/dist/framework/resolve-metric.js.map +1 -0
  188. package/dist/framework/result-builder.d.ts +72 -0
  189. package/dist/framework/result-builder.d.ts.map +1 -0
  190. package/dist/framework/result-builder.js +214 -0
  191. package/dist/framework/result-builder.js.map +1 -0
  192. package/dist/framework/result-renderers.d.ts +37 -0
  193. package/dist/framework/result-renderers.d.ts.map +1 -0
  194. package/dist/framework/result-renderers.js +62 -0
  195. package/dist/framework/result-renderers.js.map +1 -0
  196. package/dist/framework/runnable-scenario.d.ts +37 -0
  197. package/dist/framework/runnable-scenario.d.ts.map +1 -0
  198. package/dist/framework/runnable-scenario.js +9 -0
  199. package/dist/framework/runnable-scenario.js.map +1 -0
  200. package/dist/framework/scenario-executor-result.d.ts +44 -0
  201. package/dist/framework/scenario-executor-result.d.ts.map +1 -0
  202. package/dist/framework/scenario-executor-result.js +13 -0
  203. package/dist/framework/scenario-executor-result.js.map +1 -0
  204. package/dist/framework/scenario-logger.d.ts +18 -0
  205. package/dist/framework/scenario-logger.d.ts.map +1 -0
  206. package/dist/framework/scenario-logger.js +39 -0
  207. package/dist/framework/scenario-logger.js.map +1 -0
  208. package/dist/framework/scenario-metric-key.d.ts +24 -0
  209. package/dist/framework/scenario-metric-key.d.ts.map +1 -0
  210. package/dist/framework/scenario-metric-key.js +17 -0
  211. package/dist/framework/scenario-metric-key.js.map +1 -0
  212. package/dist/framework/validation.d.ts +83 -0
  213. package/dist/framework/validation.d.ts.map +1 -0
  214. package/dist/framework/validation.js +93 -0
  215. package/dist/framework/validation.js.map +1 -0
  216. package/dist/index.d.ts +35 -0
  217. package/dist/index.d.ts.map +1 -0
  218. package/dist/index.js +53 -0
  219. package/dist/index.js.map +1 -0
  220. package/dist/internal.d.ts +19 -0
  221. package/dist/internal.d.ts.map +1 -0
  222. package/dist/internal.js +16 -0
  223. package/dist/internal.js.map +1 -0
  224. package/dist/kinds/chaos/__tests__/executor.test.d.ts +6 -0
  225. package/dist/kinds/chaos/__tests__/executor.test.d.ts.map +1 -0
  226. package/dist/kinds/chaos/__tests__/executor.test.js +117 -0
  227. package/dist/kinds/chaos/__tests__/executor.test.js.map +1 -0
  228. package/dist/kinds/chaos/config.d.ts +48 -0
  229. package/dist/kinds/chaos/config.d.ts.map +1 -0
  230. package/dist/kinds/chaos/config.js +15 -0
  231. package/dist/kinds/chaos/config.js.map +1 -0
  232. package/dist/kinds/chaos/define.d.ts +32 -0
  233. package/dist/kinds/chaos/define.d.ts.map +1 -0
  234. package/dist/kinds/chaos/define.js +111 -0
  235. package/dist/kinds/chaos/define.js.map +1 -0
  236. package/dist/kinds/chaos/executor.d.ts +21 -0
  237. package/dist/kinds/chaos/executor.d.ts.map +1 -0
  238. package/dist/kinds/chaos/executor.js +107 -0
  239. package/dist/kinds/chaos/executor.js.map +1 -0
  240. package/dist/kinds/chaos/result.d.ts +43 -0
  241. package/dist/kinds/chaos/result.d.ts.map +1 -0
  242. package/dist/kinds/chaos/result.js +12 -0
  243. package/dist/kinds/chaos/result.js.map +1 -0
  244. package/dist/kinds/load/__tests__/executor.test.d.ts +6 -0
  245. package/dist/kinds/load/__tests__/executor.test.d.ts.map +1 -0
  246. package/dist/kinds/load/__tests__/executor.test.js +75 -0
  247. package/dist/kinds/load/__tests__/executor.test.js.map +1 -0
  248. package/dist/kinds/load/config.d.ts +30 -0
  249. package/dist/kinds/load/config.d.ts.map +1 -0
  250. package/dist/kinds/load/config.js +9 -0
  251. package/dist/kinds/load/config.js.map +1 -0
  252. package/dist/kinds/load/define.d.ts +47 -0
  253. package/dist/kinds/load/define.d.ts.map +1 -0
  254. package/dist/kinds/load/define.js +76 -0
  255. package/dist/kinds/load/define.js.map +1 -0
  256. package/dist/kinds/load/executor.d.ts +16 -0
  257. package/dist/kinds/load/executor.d.ts.map +1 -0
  258. package/dist/kinds/load/executor.js +90 -0
  259. package/dist/kinds/load/executor.js.map +1 -0
  260. package/dist/kinds/load/result.d.ts +21 -0
  261. package/dist/kinds/load/result.d.ts.map +1 -0
  262. package/dist/kinds/load/result.js +10 -0
  263. package/dist/kinds/load/result.js.map +1 -0
  264. package/dist/persistence/session-payload.d.ts +32 -0
  265. package/dist/persistence/session-payload.d.ts.map +1 -0
  266. package/dist/persistence/session-payload.js +46 -0
  267. package/dist/persistence/session-payload.js.map +1 -0
  268. package/dist/persistence/session-replay.d.ts +13 -0
  269. package/dist/persistence/session-replay.d.ts.map +1 -0
  270. package/dist/persistence/session-replay.js +76 -0
  271. package/dist/persistence/session-replay.js.map +1 -0
  272. package/dist/persistence/session-replay.test.d.ts +10 -0
  273. package/dist/persistence/session-replay.test.d.ts.map +1 -0
  274. package/dist/persistence/session-replay.test.js +169 -0
  275. package/dist/persistence/session-replay.test.js.map +1 -0
  276. package/dist/plugins/__tests__/loader-scenarios.test.d.ts +12 -0
  277. package/dist/plugins/__tests__/loader-scenarios.test.d.ts.map +1 -0
  278. package/dist/plugins/__tests__/loader-scenarios.test.js +61 -0
  279. package/dist/plugins/__tests__/loader-scenarios.test.js.map +1 -0
  280. package/dist/plugins/__tests__/scenario-package-discovery.test.d.ts +2 -0
  281. package/dist/plugins/__tests__/scenario-package-discovery.test.d.ts.map +1 -0
  282. package/dist/plugins/__tests__/scenario-package-discovery.test.js +43 -0
  283. package/dist/plugins/__tests__/scenario-package-discovery.test.js.map +1 -0
  284. package/dist/plugins/loader.d.ts +32 -0
  285. package/dist/plugins/loader.d.ts.map +1 -0
  286. package/dist/plugins/loader.js +119 -0
  287. package/dist/plugins/loader.js.map +1 -0
  288. package/dist/plugins/scenario-package-discovery.d.ts +23 -0
  289. package/dist/plugins/scenario-package-discovery.d.ts.map +1 -0
  290. package/dist/plugins/scenario-package-discovery.js +42 -0
  291. package/dist/plugins/scenario-package-discovery.js.map +1 -0
  292. package/dist/plugins/types.d.ts +24 -0
  293. package/dist/plugins/types.d.ts.map +1 -0
  294. package/dist/plugins/types.js +18 -0
  295. package/dist/plugins/types.js.map +1 -0
  296. package/dist/recipes/__tests__/recipes.test.d.ts +2 -0
  297. package/dist/recipes/__tests__/recipes.test.d.ts.map +1 -0
  298. package/dist/recipes/__tests__/recipes.test.js +515 -0
  299. package/dist/recipes/__tests__/recipes.test.js.map +1 -0
  300. package/dist/recipes/built-in-recipes.d.ts +16 -0
  301. package/dist/recipes/built-in-recipes.d.ts.map +1 -0
  302. package/dist/recipes/built-in-recipes.js +37 -0
  303. package/dist/recipes/built-in-recipes.js.map +1 -0
  304. package/dist/recipes/define-recipe.d.ts +29 -0
  305. package/dist/recipes/define-recipe.d.ts.map +1 -0
  306. package/dist/recipes/define-recipe.js +68 -0
  307. package/dist/recipes/define-recipe.js.map +1 -0
  308. package/dist/recipes/registry.d.ts +54 -0
  309. package/dist/recipes/registry.d.ts.map +1 -0
  310. package/dist/recipes/registry.js +89 -0
  311. package/dist/recipes/registry.js.map +1 -0
  312. package/dist/recipes/service.d.ts +61 -0
  313. package/dist/recipes/service.d.ts.map +1 -0
  314. package/dist/recipes/service.js +205 -0
  315. package/dist/recipes/service.js.map +1 -0
  316. package/dist/recipes/types.d.ts +62 -0
  317. package/dist/recipes/types.d.ts.map +1 -0
  318. package/dist/recipes/types.js +10 -0
  319. package/dist/recipes/types.js.map +1 -0
  320. package/dist/scaffold/examples.d.ts +22 -0
  321. package/dist/scaffold/examples.d.ts.map +1 -0
  322. package/dist/scaffold/examples.js +91 -0
  323. package/dist/scaffold/examples.js.map +1 -0
  324. package/dist/scope-augmentation.d.ts +70 -0
  325. package/dist/scope-augmentation.d.ts.map +1 -0
  326. package/dist/scope-augmentation.js +28 -0
  327. package/dist/scope-augmentation.js.map +1 -0
  328. package/dist/tool.d.ts +21 -0
  329. package/dist/tool.d.ts.map +1 -0
  330. package/dist/tool.js +347 -0
  331. package/dist/tool.js.map +1 -0
  332. package/dist/types/base-types.d.ts +35 -0
  333. package/dist/types/base-types.d.ts.map +1 -0
  334. package/dist/types/base-types.js +8 -0
  335. package/dist/types/base-types.js.map +1 -0
  336. package/dist/types/framework-types.d.ts +62 -0
  337. package/dist/types/framework-types.d.ts.map +1 -0
  338. package/dist/types/framework-types.js +15 -0
  339. package/dist/types/framework-types.js.map +1 -0
  340. package/dist/types/kind-types.d.ts +24 -0
  341. package/dist/types/kind-types.d.ts.map +1 -0
  342. package/dist/types/kind-types.js +22 -0
  343. package/dist/types/kind-types.js.map +1 -0
  344. package/dist/types/workload.d.ts +30 -0
  345. package/dist/types/workload.d.ts.map +1 -0
  346. package/dist/types/workload.js +20 -0
  347. package/dist/types/workload.js.map +1 -0
  348. package/package.json +120 -0
@@ -0,0 +1,76 @@
1
+ import { decodeSessionPayload } from '@opensip-cli/session-store';
2
+ /**
3
+ * Project a stored sim session back into a {@link SignalEnvelope}/{@link SimDoneResult}.
4
+ *
5
+ * The structural decode of the opaque payload is shared across tools
6
+ * (`decodeSessionPayload`); this function owns only sim's projection
7
+ * (`tool: 'sim'`, `category: 'testing'`, signal id prefix, `sim-done` result).
8
+ *
9
+ * @throws {Error | TypeError} when the stored payload is not the expected shape
10
+ * (propagated from `decodeSessionPayload`).
11
+ */
12
+ export function simReplayFromSession(stored) {
13
+ const payload = decodeSessionPayload(stored.payload, {
14
+ tool: 'sim',
15
+ requireViolationCount: true,
16
+ });
17
+ const units = payload.checks.map((check) => ({
18
+ slug: check.checkSlug,
19
+ passed: check.passed,
20
+ ...(check.violationCount === undefined ? {} : { violationCount: check.violationCount }),
21
+ durationMs: check.durationMs,
22
+ }));
23
+ const signals = payload.checks.flatMap((check, checkIndex) => check.findings.map((finding, findingIndex) => replaySignal(stored, check.checkSlug, finding, checkIndex, findingIndex)));
24
+ const envelope = {
25
+ schemaVersion: 2,
26
+ tool: 'sim',
27
+ runId: stored.id,
28
+ createdAt: stored.startedAt,
29
+ ...(stored.recipe === undefined ? {} : { recipe: stored.recipe }),
30
+ verdict: {
31
+ score: stored.score,
32
+ passed: stored.passed,
33
+ summary: payload.summary,
34
+ },
35
+ units,
36
+ signals,
37
+ };
38
+ return {
39
+ fidelity: 'projection',
40
+ envelope,
41
+ result: {
42
+ type: 'sim-done',
43
+ recipeName: stored.recipe ?? 'default',
44
+ cwd: stored.cwd,
45
+ durationMs: stored.durationMs,
46
+ envelope,
47
+ },
48
+ };
49
+ }
50
+ function replaySignal(stored, source, finding, checkIndex, findingIndex) {
51
+ return {
52
+ id: `${stored.id}:sim:${checkIndex}:${findingIndex}`,
53
+ source,
54
+ provider: 'opensip-cli',
55
+ severity: finding.severity === 'error' ? 'high' : 'medium',
56
+ category: 'testing',
57
+ ruleId: finding.ruleId,
58
+ message: finding.message,
59
+ ...(finding.suggestion === undefined ? {} : { suggestion: finding.suggestion }),
60
+ filePath: finding.filePath ?? '',
61
+ ...(finding.line === undefined ? {} : { line: finding.line }),
62
+ ...(finding.column === undefined ? {} : { column: finding.column }),
63
+ ...(finding.filePath === undefined
64
+ ? {}
65
+ : {
66
+ code: {
67
+ file: finding.filePath,
68
+ ...(finding.line === undefined ? {} : { line: finding.line }),
69
+ ...(finding.column === undefined ? {} : { column: finding.column }),
70
+ },
71
+ }),
72
+ metadata: {},
73
+ createdAt: stored.startedAt,
74
+ };
75
+ }
76
+ //# sourceMappingURL=session-replay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-replay.js","sourceRoot":"","sources":["../../src/persistence/session-replay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Unit tests for {@link simReplayFromSession} (coverage gap).
3
+ *
4
+ * `session-payload.ts` (encode) and `session-replay.ts` (decode) are inverses,
5
+ * so the happy path is a round-trip: a real {@link SignalEnvelope} →
6
+ * `buildSimulationSessionPayload` → stored payload → `simReplayFromSession`.
7
+ * The remaining tests drive each validation branch with malformed payloads.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=session-replay.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-replay.test.d.ts","sourceRoot":"","sources":["../../src/persistence/session-replay.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Unit tests for {@link simReplayFromSession} (coverage gap).
3
+ *
4
+ * `session-payload.ts` (encode) and `session-replay.ts` (decode) are inverses,
5
+ * so the happy path is a round-trip: a real {@link SignalEnvelope} →
6
+ * `buildSimulationSessionPayload` → stored payload → `simReplayFromSession`.
7
+ * The remaining tests drive each validation branch with malformed payloads.
8
+ */
9
+ import { buildSignalEnvelope } from '@opensip-cli/contracts';
10
+ import { createSignal, HOST_VERDICT_POLICY_FALLBACK } from '@opensip-cli/core';
11
+ import { describe, expect, it } from 'vitest';
12
+ import { buildSimulationSessionPayload } from './session-payload.js';
13
+ import { simReplayFromSession } from './session-replay.js';
14
+ function storedSession(payload, overrides = {}) {
15
+ return {
16
+ id: 'SIM_1',
17
+ tool: 'sim',
18
+ cwd: '/repo',
19
+ startedAt: '2026-06-08T00:00:00.000Z',
20
+ completedAt: '2026-06-08T00:00:00.000Z',
21
+ score: 75,
22
+ passed: false,
23
+ durationMs: 120,
24
+ payload,
25
+ ...overrides,
26
+ };
27
+ }
28
+ function realPayload() {
29
+ const env = buildSignalEnvelope({
30
+ tool: 'sim',
31
+ runId: 'RUN_test',
32
+ createdAt: '2026-06-08T00:00:00.000Z',
33
+ policy: HOST_VERDICT_POLICY_FALLBACK,
34
+ runFaulted: false,
35
+ units: [
36
+ { slug: 'latency', passed: false, violationCount: 1, durationMs: 10 },
37
+ { slug: 'clean', passed: true, durationMs: 2 },
38
+ ],
39
+ signals: [
40
+ createSignal({
41
+ source: 'latency',
42
+ severity: 'critical',
43
+ ruleId: 'sim:latency',
44
+ message: 'too slow',
45
+ code: { file: 'svc.ts', line: 7, column: 1 },
46
+ suggestion: 'add a cache',
47
+ }),
48
+ createSignal({
49
+ source: 'latency',
50
+ severity: 'low',
51
+ ruleId: 'sim:latency2',
52
+ message: 'minor jitter',
53
+ }),
54
+ ],
55
+ });
56
+ return buildSimulationSessionPayload(env);
57
+ }
58
+ describe('simReplayFromSession', () => {
59
+ it('round-trips a stored payload back into a projection envelope + sim-done result', () => {
60
+ const replay = simReplayFromSession(storedSession(realPayload()));
61
+ expect(replay.fidelity).toBe('projection');
62
+ expect(replay.envelope.tool).toBe('sim');
63
+ expect(replay.envelope.runId).toBe('SIM_1');
64
+ expect(replay.envelope.units.map((u) => u.slug)).toEqual(['latency', 'clean']);
65
+ expect(replay.envelope.signals.map((s) => s.severity)).toEqual(['high', 'medium']);
66
+ const located = replay.envelope.signals.find((s) => s.ruleId === 'sim:latency');
67
+ expect(located?.code).toEqual({ file: 'svc.ts', line: 7, column: 1 });
68
+ expect(located?.suggestion).toBe('add a cache');
69
+ expect(replay.result.type).toBe('sim-done');
70
+ expect(replay.result.cwd).toBe('/repo');
71
+ expect(replay.result.durationMs).toBe(120);
72
+ });
73
+ it('names the recipe when present and carries it onto the envelope', () => {
74
+ const replay = simReplayFromSession(storedSession(realPayload(), { recipe: 'example' }));
75
+ expect(replay.envelope.recipe).toBe('example');
76
+ expect(replay.result.recipeName).toBe('example');
77
+ });
78
+ it("falls back to 'default' recipe name when no recipe is set", () => {
79
+ const replay = simReplayFromSession(storedSession(realPayload()));
80
+ expect(replay.envelope.recipe).toBeUndefined();
81
+ expect(replay.result.recipeName).toBe('default');
82
+ });
83
+ it('preserves a finding with no optional location fields', () => {
84
+ const payload = {
85
+ summary: { total: 1, passed: 0, failed: 1, errors: 1, warnings: 0 },
86
+ checks: [
87
+ {
88
+ checkSlug: 'a',
89
+ passed: false,
90
+ violationCount: 1,
91
+ durationMs: 1,
92
+ findings: [{ ruleId: 'r', message: 'm', severity: 'error' }],
93
+ },
94
+ ],
95
+ };
96
+ const replay = simReplayFromSession(storedSession(payload));
97
+ const signal = replay.envelope.signals[0];
98
+ expect(signal?.filePath).toBe('');
99
+ expect(signal?.line).toBeUndefined();
100
+ expect(signal?.code).toBeUndefined();
101
+ });
102
+ describe('payload validation', () => {
103
+ const cases = [
104
+ { name: 'null payload', payload: null, message: /no replay payload/ },
105
+ { name: 'missing summary', payload: { checks: [] }, message: /summary is missing/ },
106
+ {
107
+ name: 'non-number summary field',
108
+ payload: {
109
+ summary: { total: 'x', passed: 0, failed: 0, errors: 0, warnings: 0 },
110
+ checks: [],
111
+ },
112
+ message: /total must be a number/,
113
+ },
114
+ {
115
+ name: 'missing checks[]',
116
+ payload: { summary: { total: 0, passed: 0, failed: 0, errors: 0, warnings: 0 } },
117
+ message: /missing checks\[\]/,
118
+ },
119
+ {
120
+ name: 'invalid check row',
121
+ payload: {
122
+ summary: { total: 0, passed: 0, failed: 0, errors: 0, warnings: 0 },
123
+ checks: [null],
124
+ },
125
+ message: /check row is invalid/,
126
+ },
127
+ {
128
+ name: 'check missing findings[]',
129
+ payload: {
130
+ summary: { total: 0, passed: 0, failed: 0, errors: 0, warnings: 0 },
131
+ checks: [{ checkSlug: 'a', passed: true, violationCount: 0, durationMs: 1 }],
132
+ },
133
+ message: /missing findings\[\]/,
134
+ },
135
+ {
136
+ name: 'invalid finding row',
137
+ payload: {
138
+ summary: { total: 0, passed: 0, failed: 0, errors: 0, warnings: 0 },
139
+ checks: [
140
+ { checkSlug: 'a', passed: true, violationCount: 1, durationMs: 1, findings: [42] },
141
+ ],
142
+ },
143
+ message: /finding is invalid/,
144
+ },
145
+ {
146
+ name: 'invalid finding severity',
147
+ payload: {
148
+ summary: { total: 0, passed: 0, failed: 0, errors: 0, warnings: 0 },
149
+ checks: [
150
+ {
151
+ checkSlug: 'a',
152
+ passed: true,
153
+ violationCount: 1,
154
+ durationMs: 1,
155
+ findings: [{ ruleId: 'r', message: 'm', severity: 'info' }],
156
+ },
157
+ ],
158
+ },
159
+ message: /invalid severity/,
160
+ },
161
+ ];
162
+ for (const { name, payload, message } of cases) {
163
+ it(`throws on ${name}`, () => {
164
+ expect(() => simReplayFromSession(storedSession(payload))).toThrow(message);
165
+ });
166
+ }
167
+ });
168
+ });
169
+ //# sourceMappingURL=session-replay.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-replay.test.js","sourceRoot":"","sources":["../../src/persistence/session-replay.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @fileoverview Covers the simulation plugin loader's SCENARIO registration
3
+ * path (the recipe path is covered by ../../__tests__/plugin-loader.test.ts).
4
+ *
5
+ * A discovered `.mjs` plugin that exports a `scenarios` array drives
6
+ * `registerScenariosArray` → `isValidScenario` → `tryRegisterScenario`. We
7
+ * assert the real behaviour: well-shaped scenarios register into the live
8
+ * scope registry, malformed items are skipped (not registered, not fatal), and
9
+ * a non-array `scenarios` export is rejected without registering anything.
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=loader-scenarios.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader-scenarios.test.d.ts","sourceRoot":"","sources":["../../../src/plugins/__tests__/loader-scenarios.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * @fileoverview Covers the simulation plugin loader's SCENARIO registration
3
+ * path (the recipe path is covered by ../../__tests__/plugin-loader.test.ts).
4
+ *
5
+ * A discovered `.mjs` plugin that exports a `scenarios` array drives
6
+ * `registerScenariosArray` → `isValidScenario` → `tryRegisterScenario`. We
7
+ * assert the real behaviour: well-shaped scenarios register into the live
8
+ * scope registry, malformed items are skipped (not registered, not fatal), and
9
+ * a non-array `scenarios` export is rejected without registering anything.
10
+ */
11
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
12
+ import { tmpdir } from 'node:os';
13
+ import { join } from 'node:path';
14
+ import { enterScope, RunScope } from '@opensip-cli/core';
15
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
16
+ import { currentScenarioRegistry } from '../../framework/registry.js';
17
+ import { simulationTool } from '../../tool.js';
18
+ import { loadAllSimPlugins } from '../loader.js';
19
+ let testDir;
20
+ beforeEach(() => {
21
+ const scope = new RunScope();
22
+ Object.assign(scope, simulationTool.contributeScope?.() ?? {});
23
+ enterScope(scope);
24
+ testDir = mkdtempSync(join(tmpdir(), 'sim-loader-scenarios-'));
25
+ });
26
+ afterEach(() => {
27
+ rmSync(testDir, { recursive: true, force: true });
28
+ });
29
+ function writeScenarioPlugin(body) {
30
+ const dir = join(testDir, 'opensip-cli', 'sim', 'scenarios');
31
+ mkdirSync(dir, { recursive: true });
32
+ writeFileSync(join(dir, 'plugin.mjs'), body);
33
+ }
34
+ describe('loadAllSimPlugins — scenario registration', () => {
35
+ it('registers well-shaped scenarios from a plugin export into the scope registry', async () => {
36
+ writeScenarioPlugin('export const scenarios = [' +
37
+ '{ id: "plug-load-1", name: "plug-load-1", kind: "load", tags: [], run: async () => ({ kind: "load", scenarioId: "plug-load-1", passed: true, durationMs: 0, signals: [] }) }' +
38
+ '];\n');
39
+ const result = await loadAllSimPlugins(testDir);
40
+ expect(result.totals.scenarios).toBe(1);
41
+ expect(currentScenarioRegistry().get('plug-load-1')).toBeDefined();
42
+ });
43
+ it('skips malformed scenario items but still registers the valid ones', async () => {
44
+ writeScenarioPlugin('export const scenarios = [' +
45
+ '{ id: "missing-run" },' + // not a valid RunnableScenario (no kind/run) → skipped
46
+ '{ id: "plug-load-2", name: "plug-load-2", kind: "load", tags: [], run: async () => ({ kind: "load", scenarioId: "plug-load-2", passed: true, durationMs: 0, signals: [] }) }' +
47
+ '];\n');
48
+ const result = await loadAllSimPlugins(testDir);
49
+ // Only the well-shaped scenario registers; the malformed item is dropped.
50
+ expect(result.totals.scenarios).toBe(1);
51
+ expect(currentScenarioRegistry().get('plug-load-2')).toBeDefined();
52
+ expect(currentScenarioRegistry().get('missing-run')).toBeUndefined();
53
+ });
54
+ it('rejects a non-array scenarios export without registering anything', async () => {
55
+ writeScenarioPlugin('export const scenarios = "not-an-array";\n');
56
+ const result = await loadAllSimPlugins(testDir);
57
+ expect(result.totals.scenarios ?? 0).toBe(0);
58
+ expect(currentScenarioRegistry().size).toBe(0);
59
+ });
60
+ });
61
+ //# sourceMappingURL=loader-scenarios.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader-scenarios.test.js","sourceRoot":"","sources":["../../../src/plugins/__tests__/loader-scenarios.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=scenario-package-discovery.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario-package-discovery.test.d.ts","sourceRoot":"","sources":["../../../src/plugins/__tests__/scenario-package-discovery.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,43 @@
1
+ import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
+ import { readScenarioPackagePreferences } from '../scenario-package-discovery.js';
6
+ let testDir;
7
+ beforeEach(() => {
8
+ testDir = mkdtempSync(join(tmpdir(), 'opensip-scenario-pkg-disc-'));
9
+ });
10
+ afterEach(() => {
11
+ rmSync(testDir, { recursive: true, force: true });
12
+ });
13
+ describe('readScenarioPackagePreferences', () => {
14
+ it('reads scenarioPackages and autoDiscoverScenarios from project config', () => {
15
+ writeFileSync(join(testDir, 'opensip-cli.config.yml'), `plugins:
16
+ scenarioPackages:
17
+ - "@opensip-cli/scenarios-load-default"
18
+ autoDiscoverScenarios: false
19
+ `);
20
+ const prefs = readScenarioPackagePreferences(testDir);
21
+ expect(prefs.scenarioPackages).toEqual(['@opensip-cli/scenarios-load-default']);
22
+ expect(prefs.autoDiscoverScenarios).toBe(false);
23
+ });
24
+ it('reads packageScopes from project config', () => {
25
+ writeFileSync(join(testDir, 'opensip-cli.config.yml'), `plugins:
26
+ packageScopes:
27
+ - "@acme"
28
+ - "@my-org"
29
+ `);
30
+ const prefs = readScenarioPackagePreferences(testDir);
31
+ expect(prefs.packageScopes).toEqual(['@acme', '@my-org']);
32
+ });
33
+ it('returns empty object when config has no plugins section', () => {
34
+ writeFileSync(join(testDir, 'opensip-cli.config.yml'), `simulation: { enabled: true }
35
+ `);
36
+ const prefs = readScenarioPackagePreferences(testDir);
37
+ expect(prefs).toEqual({});
38
+ });
39
+ it('returns empty object when no config file exists', () => {
40
+ expect(readScenarioPackagePreferences(testDir)).toEqual({});
41
+ });
42
+ });
43
+ //# sourceMappingURL=scenario-package-discovery.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario-package-discovery.test.js","sourceRoot":"","sources":["../../../src/plugins/__tests__/scenario-package-discovery.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAErE,OAAO,EAAE,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAElF,IAAI,OAAe,CAAC;AAEpB,UAAU,CAAC,GAAG,EAAE;IACd,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,4BAA4B,CAAC,CAAC,CAAC;AACtE,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,GAAG,EAAE;IACb,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,aAAa,CACX,IAAI,CAAC,OAAO,EAAE,wBAAwB,CAAC,EACvC;;;;CAIL,CACI,CAAC;QACF,MAAM,KAAK,GAAG,8BAA8B,CAAC,OAAO,CAAC,CAAC;QACtD,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,qCAAqC,CAAC,CAAC,CAAC;QAChF,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,aAAa,CACX,IAAI,CAAC,OAAO,EAAE,wBAAwB,CAAC,EACvC;;;;CAIL,CACI,CAAC;QACF,MAAM,KAAK,GAAG,8BAA8B,CAAC,OAAO,CAAC,CAAC;QACtD,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,aAAa,CACX,IAAI,CAAC,OAAO,EAAE,wBAAwB,CAAC,EACvC;CACL,CACI,CAAC;QACF,MAAM,KAAK,GAAG,8BAA8B,CAAC,OAAO,CAAC,CAAC;QACtD,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,CAAC,8BAA8B,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @fileoverview Simulation plugin loader — adapter over core's generic
3
+ * loader.
4
+ *
5
+ * Core owns the discovery, dynamic-import, error-wrap, and log
6
+ * machinery. This file supplies the sim-specific `registerExports`
7
+ * callback that knows how to interpret a `SimPluginExports`-shaped
8
+ * module: both `scenarios: RunnableScenario[]` and
9
+ * `recipes: SimulationRecipe[]` are explicit arrays — the loader walks
10
+ * each and registers items into the simulation registries. There is no
11
+ * import-side-effect channel.
12
+ *
13
+ * Public API: `loadAllSimPlugins(projectDir)` — the sim equivalent of
14
+ * fitness's `loadAllPlugins('fit', projectDir)`.
15
+ */
16
+ import type { PluginLayout, PluginLoadResult } from '@opensip-cli/core';
17
+ /**
18
+ * Simulation's project-local plugin layout — user scenarios/recipes live
19
+ * under `<project>/opensip-cli/sim/{scenarios,recipes}/`. Exported so
20
+ * the `simulationTool` descriptor (`Tool.pluginLayout`) and the CLI's
21
+ * `plugin` command share one source of truth (ADR-0009 corollary 1).
22
+ */
23
+ export declare const SIM_PLUGIN_LAYOUT: PluginLayout;
24
+ /**
25
+ * Discover and load every sim-domain plugin for a project. Plugins
26
+ * are loaded sequentially to keep registration order deterministic.
27
+ *
28
+ * Without `projectDir`, no plugins are discovered — there is no
29
+ * user-global fallback, by design.
30
+ */
31
+ export declare function loadAllSimPlugins(projectDir?: string): Promise<PluginLoadResult>;
32
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/plugins/loader.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;GAcG;AAUH,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAGjB,MAAM,mBAAmB,CAAC;AAE3B;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,YAG/B,CAAC;AAkGF;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAEtF"}
@@ -0,0 +1,119 @@
1
+ // @fitness-ignore-file error-handling-quality -- tryRegisterRecipe/tryRegisterScenario translate registry throws (duplicate-id collisions) into a boolean "not newly registered" return per their documented JSDoc contract; the registry's own logging/duplicate policy is the source of truth, this layer just surfaces it as a flag.
2
+ /**
3
+ * @fileoverview Simulation plugin loader — adapter over core's generic
4
+ * loader.
5
+ *
6
+ * Core owns the discovery, dynamic-import, error-wrap, and log
7
+ * machinery. This file supplies the sim-specific `registerExports`
8
+ * callback that knows how to interpret a `SimPluginExports`-shaped
9
+ * module: both `scenarios: RunnableScenario[]` and
10
+ * `recipes: SimulationRecipe[]` are explicit arrays — the loader walks
11
+ * each and registers items into the simulation registries. There is no
12
+ * import-side-effect channel.
13
+ *
14
+ * Public API: `loadAllSimPlugins(projectDir)` — the sim equivalent of
15
+ * fitness's `loadAllPlugins('fit', projectDir)`.
16
+ */
17
+ import { loadAllPlugins } from '@opensip-cli/core';
18
+ import { currentScenarioRegistry } from '../framework/registry.js';
19
+ import { currentSimulationRecipeRegistry } from '../recipes/registry.js';
20
+ /**
21
+ * Simulation's project-local plugin layout — user scenarios/recipes live
22
+ * under `<project>/opensip-cli/sim/{scenarios,recipes}/`. Exported so
23
+ * the `simulationTool` descriptor (`Tool.pluginLayout`) and the CLI's
24
+ * `plugin` command share one source of truth (ADR-0009 corollary 1).
25
+ */
26
+ export const SIM_PLUGIN_LAYOUT = {
27
+ domain: 'sim',
28
+ userSubdirs: ['scenarios', 'recipes'],
29
+ };
30
+ /** Register one recipe; returns true if newly registered. Duplicate
31
+ * recipes throw — caught here and reported as not-newly-registered,
32
+ * matching the prior behavior of silently skipping duplicates. */
33
+ function tryRegisterRecipe(recipe) {
34
+ try {
35
+ currentSimulationRecipeRegistry().register(recipe, { allowOverwrite: false });
36
+ return true;
37
+ }
38
+ catch {
39
+ return false;
40
+ }
41
+ }
42
+ /** Register one scenario; returns true if newly registered. Duplicate
43
+ * scenarios (same id) silently skip via the registry's
44
+ * `duplicatePolicy: 'silent-skip'`. A name-collision with a different
45
+ * id throws — surfaced to the caller as `false`. */
46
+ function tryRegisterScenario(scenario) {
47
+ const registry = currentScenarioRegistry();
48
+ const before = registry.size;
49
+ try {
50
+ registry.register(scenario);
51
+ }
52
+ catch {
53
+ return false;
54
+ }
55
+ return registry.size > before;
56
+ }
57
+ function isValidRecipe(value) {
58
+ return value !== null && typeof value === 'object' && 'id' in value && 'name' in value;
59
+ }
60
+ function isValidScenario(value) {
61
+ return (value !== null &&
62
+ typeof value === 'object' &&
63
+ 'id' in value &&
64
+ 'kind' in value &&
65
+ 'run' in value);
66
+ }
67
+ function registerScenariosArray(scenariosField, ctx) {
68
+ if (scenariosField === undefined)
69
+ return 0;
70
+ if (!Array.isArray(scenariosField)) {
71
+ ctx.warn('plugin.loader.invalid_scenarios_export', `Plugin "${ctx.plugin.namespace}" exports "scenarios" but it is not an array — skipping scenario registration.`);
72
+ return 0;
73
+ }
74
+ let scenariosRegistered = 0;
75
+ for (const [index, scenario] of scenariosField.entries()) {
76
+ if (!isValidScenario(scenario)) {
77
+ ctx.warn('plugin.loader.invalid_scenario_item', `Plugin "${ctx.plugin.namespace}" scenarios[${index}] is not a valid RunnableScenario (missing id, kind, or run) — skipping.`, { index });
78
+ continue;
79
+ }
80
+ if (tryRegisterScenario(scenario))
81
+ scenariosRegistered++;
82
+ }
83
+ return scenariosRegistered;
84
+ }
85
+ function registerRecipesArray(recipesField, ctx) {
86
+ if (recipesField === undefined)
87
+ return 0;
88
+ if (!Array.isArray(recipesField)) {
89
+ ctx.warn('plugin.loader.invalid_recipes_export', `Plugin "${ctx.plugin.namespace}" exports "recipes" but it is not an array — skipping recipe registration.`);
90
+ return 0;
91
+ }
92
+ let recipesRegistered = 0;
93
+ for (const [index, recipe] of recipesField.entries()) {
94
+ if (!isValidRecipe(recipe)) {
95
+ ctx.warn('plugin.loader.invalid_recipe_item', `Plugin "${ctx.plugin.namespace}" recipes[${index}] is not a valid SimulationRecipe (missing id or name) — skipping.`, { index });
96
+ continue;
97
+ }
98
+ if (tryRegisterRecipe(recipe))
99
+ recipesRegistered++;
100
+ }
101
+ return recipesRegistered;
102
+ }
103
+ function registerSimExports(mod, ctx) {
104
+ const exports = mod;
105
+ const scenariosRegistered = registerScenariosArray(exports.scenarios, ctx);
106
+ const recipesRegistered = registerRecipesArray(exports.recipes, ctx);
107
+ return { scenarios: scenariosRegistered, recipes: recipesRegistered };
108
+ }
109
+ /**
110
+ * Discover and load every sim-domain plugin for a project. Plugins
111
+ * are loaded sequentially to keep registration order deterministic.
112
+ *
113
+ * Without `projectDir`, no plugins are discovered — there is no
114
+ * user-global fallback, by design.
115
+ */
116
+ export async function loadAllSimPlugins(projectDir) {
117
+ return loadAllPlugins(SIM_PLUGIN_LAYOUT, projectDir, registerSimExports);
118
+ }
119
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/plugins/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @fileoverview The `plugins.{scenarioPackages,autoDiscoverScenarios,packageScopes}`
3
+ * preference reader.
4
+ *
5
+ * Scenario-pack discovery + resolution (the `<scope>/scenarios-*` name-pattern
6
+ * walk, scope merging, explicit-name resolution, the single-core guard) lives in
7
+ * the GENERIC capability substrate (`@opensip-cli/core`) now. This module keeps
8
+ * only the sim-side reader for the documented config keys — sim resolves its own
9
+ * preference without depending on `@opensip-cli/config`, then hands the result
10
+ * to the generic loader.
11
+ */
12
+ /**
13
+ * Read `plugins.scenarioPackages`, `plugins.autoDiscoverScenarios`, and
14
+ * `plugins.packageScopes` from the project's opensip-cli.config.yml without a
15
+ * full schema parse. Mirrors the inline-yaml-read pattern used by
16
+ * `readProjectPluginsList()`.
17
+ */
18
+ export declare function readScenarioPackagePreferences(projectDir: string): {
19
+ readonly scenarioPackages?: readonly string[];
20
+ readonly autoDiscoverScenarios?: boolean;
21
+ readonly packageScopes?: readonly string[];
22
+ };
23
+ //# sourceMappingURL=scenario-package-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario-package-discovery.d.ts","sourceRoot":"","sources":["../../src/plugins/scenario-package-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAAC,UAAU,EAAE,MAAM,GAAG;IAClE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IACzC,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C,CAsBA"}