@substrate-ai/factory 0.20.1 → 0.20.3

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 (486) hide show
  1. package/README.md +39 -0
  2. package/package.json +6 -3
  3. package/dist/__tests__/config.test.d.ts +0 -11
  4. package/dist/__tests__/config.test.d.ts.map +0 -1
  5. package/dist/__tests__/config.test.js +0 -215
  6. package/dist/__tests__/config.test.js.map +0 -1
  7. package/dist/__tests__/factory-run-command.test.d.ts +0 -12
  8. package/dist/__tests__/factory-run-command.test.d.ts.map +0 -1
  9. package/dist/__tests__/factory-run-command.test.js +0 -454
  10. package/dist/__tests__/factory-run-command.test.js.map +0 -1
  11. package/dist/__tests__/factory-validate-command.test.d.ts +0 -15
  12. package/dist/__tests__/factory-validate-command.test.d.ts.map +0 -1
  13. package/dist/__tests__/factory-validate-command.test.js +0 -339
  14. package/dist/__tests__/factory-validate-command.test.js.map +0 -1
  15. package/dist/__tests__/fixtures/advanced-cross-project-validation.dot.d.ts +0 -72
  16. package/dist/__tests__/fixtures/advanced-cross-project-validation.dot.d.ts.map +0 -1
  17. package/dist/__tests__/fixtures/advanced-cross-project-validation.dot.js +0 -121
  18. package/dist/__tests__/fixtures/advanced-cross-project-validation.dot.js.map +0 -1
  19. package/dist/__tests__/fixtures/llm-edge-routing.dot.d.ts +0 -28
  20. package/dist/__tests__/fixtures/llm-edge-routing.dot.d.ts.map +0 -1
  21. package/dist/__tests__/fixtures/llm-edge-routing.dot.js +0 -55
  22. package/dist/__tests__/fixtures/llm-edge-routing.dot.js.map +0 -1
  23. package/dist/__tests__/fixtures/manager-loop.dot.d.ts +0 -34
  24. package/dist/__tests__/fixtures/manager-loop.dot.d.ts.map +0 -1
  25. package/dist/__tests__/fixtures/manager-loop.dot.js +0 -61
  26. package/dist/__tests__/fixtures/manager-loop.dot.js.map +0 -1
  27. package/dist/__tests__/fixtures/parallel-fan-out-fan-in.dot.d.ts +0 -42
  28. package/dist/__tests__/fixtures/parallel-fan-out-fan-in.dot.d.ts.map +0 -1
  29. package/dist/__tests__/fixtures/parallel-fan-out-fan-in.dot.js +0 -118
  30. package/dist/__tests__/fixtures/parallel-fan-out-fan-in.dot.js.map +0 -1
  31. package/dist/__tests__/fixtures/subgraph-parent.dot.d.ts +0 -35
  32. package/dist/__tests__/fixtures/subgraph-parent.dot.d.ts.map +0 -1
  33. package/dist/__tests__/fixtures/subgraph-parent.dot.js +0 -69
  34. package/dist/__tests__/fixtures/subgraph-parent.dot.js.map +0 -1
  35. package/dist/__tests__/integration/advanced-graph-events.test.d.ts +0 -19
  36. package/dist/__tests__/integration/advanced-graph-events.test.d.ts.map +0 -1
  37. package/dist/__tests__/integration/advanced-graph-events.test.js +0 -288
  38. package/dist/__tests__/integration/advanced-graph-events.test.js.map +0 -1
  39. package/dist/__tests__/integration/checkpoint-resume.test.d.ts +0 -10
  40. package/dist/__tests__/integration/checkpoint-resume.test.d.ts.map +0 -1
  41. package/dist/__tests__/integration/checkpoint-resume.test.js +0 -125
  42. package/dist/__tests__/integration/checkpoint-resume.test.js.map +0 -1
  43. package/dist/__tests__/integration/conditional-pipeline.test.d.ts +0 -10
  44. package/dist/__tests__/integration/conditional-pipeline.test.d.ts.map +0 -1
  45. package/dist/__tests__/integration/conditional-pipeline.test.js +0 -106
  46. package/dist/__tests__/integration/conditional-pipeline.test.js.map +0 -1
  47. package/dist/__tests__/integration/convergence-validation.test.d.ts +0 -14
  48. package/dist/__tests__/integration/convergence-validation.test.d.ts.map +0 -1
  49. package/dist/__tests__/integration/convergence-validation.test.js +0 -449
  50. package/dist/__tests__/integration/convergence-validation.test.js.map +0 -1
  51. package/dist/__tests__/integration/epic44-coverage-gate.test.d.ts +0 -12
  52. package/dist/__tests__/integration/epic44-coverage-gate.test.d.ts.map +0 -1
  53. package/dist/__tests__/integration/epic44-coverage-gate.test.js +0 -58
  54. package/dist/__tests__/integration/epic44-coverage-gate.test.js.map +0 -1
  55. package/dist/__tests__/integration/epic45-coverage-gate.test.d.ts +0 -11
  56. package/dist/__tests__/integration/epic45-coverage-gate.test.d.ts.map +0 -1
  57. package/dist/__tests__/integration/epic45-coverage-gate.test.js +0 -64
  58. package/dist/__tests__/integration/epic45-coverage-gate.test.js.map +0 -1
  59. package/dist/__tests__/integration/epic46-scenario-primary-executor.test.d.ts +0 -2
  60. package/dist/__tests__/integration/epic46-scenario-primary-executor.test.d.ts.map +0 -1
  61. package/dist/__tests__/integration/epic46-scenario-primary-executor.test.js +0 -285
  62. package/dist/__tests__/integration/epic46-scenario-primary-executor.test.js.map +0 -1
  63. package/dist/__tests__/integration/events.test.d.ts +0 -8
  64. package/dist/__tests__/integration/events.test.d.ts.map +0 -1
  65. package/dist/__tests__/integration/events.test.js +0 -194
  66. package/dist/__tests__/integration/events.test.js.map +0 -1
  67. package/dist/__tests__/integration/graphs.d.ts +0 -59
  68. package/dist/__tests__/integration/graphs.d.ts.map +0 -1
  69. package/dist/__tests__/integration/graphs.js +0 -164
  70. package/dist/__tests__/integration/graphs.js.map +0 -1
  71. package/dist/__tests__/integration/helpers.d.ts +0 -127
  72. package/dist/__tests__/integration/helpers.d.ts.map +0 -1
  73. package/dist/__tests__/integration/helpers.js +0 -167
  74. package/dist/__tests__/integration/helpers.js.map +0 -1
  75. package/dist/__tests__/integration/integrity.test.d.ts +0 -8
  76. package/dist/__tests__/integration/integrity.test.d.ts.map +0 -1
  77. package/dist/__tests__/integration/integrity.test.js +0 -198
  78. package/dist/__tests__/integration/integrity.test.js.map +0 -1
  79. package/dist/__tests__/integration/llm-edge-routing.test.d.ts +0 -21
  80. package/dist/__tests__/integration/llm-edge-routing.test.d.ts.map +0 -1
  81. package/dist/__tests__/integration/llm-edge-routing.test.js +0 -341
  82. package/dist/__tests__/integration/llm-edge-routing.test.js.map +0 -1
  83. package/dist/__tests__/integration/manager-loop.test.d.ts +0 -24
  84. package/dist/__tests__/integration/manager-loop.test.d.ts.map +0 -1
  85. package/dist/__tests__/integration/manager-loop.test.js +0 -276
  86. package/dist/__tests__/integration/manager-loop.test.js.map +0 -1
  87. package/dist/__tests__/integration/multi-type-graph.test.d.ts +0 -10
  88. package/dist/__tests__/integration/multi-type-graph.test.d.ts.map +0 -1
  89. package/dist/__tests__/integration/multi-type-graph.test.js +0 -100
  90. package/dist/__tests__/integration/multi-type-graph.test.js.map +0 -1
  91. package/dist/__tests__/integration/parallel-fan-out-fan-in.test.d.ts +0 -22
  92. package/dist/__tests__/integration/parallel-fan-out-fan-in.test.d.ts.map +0 -1
  93. package/dist/__tests__/integration/parallel-fan-out-fan-in.test.js +0 -515
  94. package/dist/__tests__/integration/parallel-fan-out-fan-in.test.js.map +0 -1
  95. package/dist/__tests__/integration/persistence.test.d.ts +0 -8
  96. package/dist/__tests__/integration/persistence.test.d.ts.map +0 -1
  97. package/dist/__tests__/integration/persistence.test.js +0 -129
  98. package/dist/__tests__/integration/persistence.test.js.map +0 -1
  99. package/dist/__tests__/integration/pipeline-templates-integration.test.d.ts +0 -16
  100. package/dist/__tests__/integration/pipeline-templates-integration.test.d.ts.map +0 -1
  101. package/dist/__tests__/integration/pipeline-templates-integration.test.js +0 -171
  102. package/dist/__tests__/integration/pipeline-templates-integration.test.js.map +0 -1
  103. package/dist/__tests__/integration/scenario-pipeline.test.d.ts +0 -11
  104. package/dist/__tests__/integration/scenario-pipeline.test.d.ts.map +0 -1
  105. package/dist/__tests__/integration/scenario-pipeline.test.js +0 -243
  106. package/dist/__tests__/integration/scenario-pipeline.test.js.map +0 -1
  107. package/dist/__tests__/integration/stylesheet-application.test.d.ts +0 -12
  108. package/dist/__tests__/integration/stylesheet-application.test.d.ts.map +0 -1
  109. package/dist/__tests__/integration/stylesheet-application.test.js +0 -119
  110. package/dist/__tests__/integration/stylesheet-application.test.js.map +0 -1
  111. package/dist/__tests__/integration/subgraph-execution.test.d.ts +0 -24
  112. package/dist/__tests__/integration/subgraph-execution.test.d.ts.map +0 -1
  113. package/dist/__tests__/integration/subgraph-execution.test.js +0 -291
  114. package/dist/__tests__/integration/subgraph-execution.test.js.map +0 -1
  115. package/dist/__tests__/integration/validation-errors.test.d.ts +0 -8
  116. package/dist/__tests__/integration/validation-errors.test.d.ts.map +0 -1
  117. package/dist/__tests__/integration/validation-errors.test.js +0 -150
  118. package/dist/__tests__/integration/validation-errors.test.js.map +0 -1
  119. package/dist/agent/__tests__/loop-detection.test.d.ts +0 -2
  120. package/dist/agent/__tests__/loop-detection.test.d.ts.map +0 -1
  121. package/dist/agent/__tests__/loop-detection.test.js +0 -236
  122. package/dist/agent/__tests__/loop-detection.test.js.map +0 -1
  123. package/dist/agent/__tests__/loop.test.d.ts +0 -2
  124. package/dist/agent/__tests__/loop.test.d.ts.map +0 -1
  125. package/dist/agent/__tests__/loop.test.js +0 -868
  126. package/dist/agent/__tests__/loop.test.js.map +0 -1
  127. package/dist/agent/__tests__/truncation.test.d.ts +0 -2
  128. package/dist/agent/__tests__/truncation.test.d.ts.map +0 -1
  129. package/dist/agent/__tests__/truncation.test.js +0 -276
  130. package/dist/agent/__tests__/truncation.test.js.map +0 -1
  131. package/dist/agent/tools/__tests__/anthropic-tools.test.d.ts +0 -6
  132. package/dist/agent/tools/__tests__/anthropic-tools.test.d.ts.map +0 -1
  133. package/dist/agent/tools/__tests__/anthropic-tools.test.js +0 -49
  134. package/dist/agent/tools/__tests__/anthropic-tools.test.js.map +0 -1
  135. package/dist/agent/tools/__tests__/environment.test.d.ts +0 -6
  136. package/dist/agent/tools/__tests__/environment.test.d.ts.map +0 -1
  137. package/dist/agent/tools/__tests__/environment.test.js +0 -33
  138. package/dist/agent/tools/__tests__/environment.test.js.map +0 -1
  139. package/dist/agent/tools/__tests__/gemini-tools.test.d.ts +0 -6
  140. package/dist/agent/tools/__tests__/gemini-tools.test.d.ts.map +0 -1
  141. package/dist/agent/tools/__tests__/gemini-tools.test.js +0 -98
  142. package/dist/agent/tools/__tests__/gemini-tools.test.js.map +0 -1
  143. package/dist/agent/tools/__tests__/openai-tools.test.d.ts +0 -6
  144. package/dist/agent/tools/__tests__/openai-tools.test.d.ts.map +0 -1
  145. package/dist/agent/tools/__tests__/openai-tools.test.js +0 -53
  146. package/dist/agent/tools/__tests__/openai-tools.test.js.map +0 -1
  147. package/dist/agent/tools/__tests__/patch.test.d.ts +0 -6
  148. package/dist/agent/tools/__tests__/patch.test.d.ts.map +0 -1
  149. package/dist/agent/tools/__tests__/patch.test.js +0 -116
  150. package/dist/agent/tools/__tests__/patch.test.js.map +0 -1
  151. package/dist/agent/tools/__tests__/profiles.test.d.ts +0 -6
  152. package/dist/agent/tools/__tests__/profiles.test.d.ts.map +0 -1
  153. package/dist/agent/tools/__tests__/profiles.test.js +0 -125
  154. package/dist/agent/tools/__tests__/profiles.test.js.map +0 -1
  155. package/dist/agent/tools/__tests__/registry.test.d.ts +0 -6
  156. package/dist/agent/tools/__tests__/registry.test.d.ts.map +0 -1
  157. package/dist/agent/tools/__tests__/registry.test.js +0 -94
  158. package/dist/agent/tools/__tests__/registry.test.js.map +0 -1
  159. package/dist/agent/tools/__tests__/shared.test.d.ts +0 -6
  160. package/dist/agent/tools/__tests__/shared.test.d.ts.map +0 -1
  161. package/dist/agent/tools/__tests__/shared.test.js +0 -131
  162. package/dist/agent/tools/__tests__/shared.test.js.map +0 -1
  163. package/dist/backend/__tests__/direct-backend.test.d.ts +0 -14
  164. package/dist/backend/__tests__/direct-backend.test.d.ts.map +0 -1
  165. package/dist/backend/__tests__/direct-backend.test.js +0 -393
  166. package/dist/backend/__tests__/direct-backend.test.js.map +0 -1
  167. package/dist/backend/__tests__/direct-bootstrap.test.d.ts +0 -7
  168. package/dist/backend/__tests__/direct-bootstrap.test.d.ts.map +0 -1
  169. package/dist/backend/__tests__/direct-bootstrap.test.js +0 -177
  170. package/dist/backend/__tests__/direct-bootstrap.test.js.map +0 -1
  171. package/dist/backend/__tests__/mock-backend.test.d.ts +0 -7
  172. package/dist/backend/__tests__/mock-backend.test.d.ts.map +0 -1
  173. package/dist/backend/__tests__/mock-backend.test.js +0 -273
  174. package/dist/backend/__tests__/mock-backend.test.js.map +0 -1
  175. package/dist/backend/__tests__/parity.test.d.ts +0 -17
  176. package/dist/backend/__tests__/parity.test.d.ts.map +0 -1
  177. package/dist/backend/__tests__/parity.test.js +0 -411
  178. package/dist/backend/__tests__/parity.test.js.map +0 -1
  179. package/dist/context/__tests__/auto-summarizer.test.d.ts +0 -14
  180. package/dist/context/__tests__/auto-summarizer.test.d.ts.map +0 -1
  181. package/dist/context/__tests__/auto-summarizer.test.js +0 -189
  182. package/dist/context/__tests__/auto-summarizer.test.js.map +0 -1
  183. package/dist/context/__tests__/context-cli-command.test.d.ts +0 -7
  184. package/dist/context/__tests__/context-cli-command.test.d.ts.map +0 -1
  185. package/dist/context/__tests__/context-cli-command.test.js +0 -331
  186. package/dist/context/__tests__/context-cli-command.test.js.map +0 -1
  187. package/dist/context/__tests__/pyramid-summary-integration.test.d.ts +0 -2
  188. package/dist/context/__tests__/pyramid-summary-integration.test.d.ts.map +0 -1
  189. package/dist/context/__tests__/pyramid-summary-integration.test.js +0 -533
  190. package/dist/context/__tests__/pyramid-summary-integration.test.js.map +0 -1
  191. package/dist/context/__tests__/summarizer.test.d.ts +0 -2
  192. package/dist/context/__tests__/summarizer.test.d.ts.map +0 -1
  193. package/dist/context/__tests__/summarizer.test.js +0 -189
  194. package/dist/context/__tests__/summarizer.test.js.map +0 -1
  195. package/dist/context/__tests__/summary-cache.test.d.ts +0 -2
  196. package/dist/context/__tests__/summary-cache.test.d.ts.map +0 -1
  197. package/dist/context/__tests__/summary-cache.test.js +0 -214
  198. package/dist/context/__tests__/summary-cache.test.js.map +0 -1
  199. package/dist/context/__tests__/summary-metrics.test.d.ts +0 -2
  200. package/dist/context/__tests__/summary-metrics.test.d.ts.map +0 -1
  201. package/dist/context/__tests__/summary-metrics.test.js +0 -172
  202. package/dist/context/__tests__/summary-metrics.test.js.map +0 -1
  203. package/dist/context/__tests__/summary-types.test.d.ts +0 -2
  204. package/dist/context/__tests__/summary-types.test.d.ts.map +0 -1
  205. package/dist/context/__tests__/summary-types.test.js +0 -130
  206. package/dist/context/__tests__/summary-types.test.js.map +0 -1
  207. package/dist/convergence/__tests__/budget.test.d.ts +0 -6
  208. package/dist/convergence/__tests__/budget.test.d.ts.map +0 -1
  209. package/dist/convergence/__tests__/budget.test.js +0 -187
  210. package/dist/convergence/__tests__/budget.test.js.map +0 -1
  211. package/dist/convergence/__tests__/controller.test.d.ts +0 -9
  212. package/dist/convergence/__tests__/controller.test.d.ts.map +0 -1
  213. package/dist/convergence/__tests__/controller.test.js +0 -585
  214. package/dist/convergence/__tests__/controller.test.js.map +0 -1
  215. package/dist/convergence/__tests__/dual-signal.test.d.ts +0 -14
  216. package/dist/convergence/__tests__/dual-signal.test.d.ts.map +0 -1
  217. package/dist/convergence/__tests__/dual-signal.test.js +0 -123
  218. package/dist/convergence/__tests__/dual-signal.test.js.map +0 -1
  219. package/dist/convergence/__tests__/epic46-integration.test.d.ts +0 -15
  220. package/dist/convergence/__tests__/epic46-integration.test.d.ts.map +0 -1
  221. package/dist/convergence/__tests__/epic46-integration.test.js +0 -522
  222. package/dist/convergence/__tests__/epic46-integration.test.js.map +0 -1
  223. package/dist/convergence/__tests__/plateau.test.d.ts +0 -6
  224. package/dist/convergence/__tests__/plateau.test.d.ts.map +0 -1
  225. package/dist/convergence/__tests__/plateau.test.js +0 -163
  226. package/dist/convergence/__tests__/plateau.test.js.map +0 -1
  227. package/dist/convergence/__tests__/remediation.test.d.ts +0 -11
  228. package/dist/convergence/__tests__/remediation.test.d.ts.map +0 -1
  229. package/dist/convergence/__tests__/remediation.test.js +0 -209
  230. package/dist/convergence/__tests__/remediation.test.js.map +0 -1
  231. package/dist/convergence/__tests__/scenario-primary.test.d.ts +0 -13
  232. package/dist/convergence/__tests__/scenario-primary.test.d.ts.map +0 -1
  233. package/dist/convergence/__tests__/scenario-primary.test.js +0 -183
  234. package/dist/convergence/__tests__/scenario-primary.test.js.map +0 -1
  235. package/dist/factory-command.test.d.ts +0 -8
  236. package/dist/factory-command.test.d.ts.map +0 -1
  237. package/dist/factory-command.test.js +0 -304
  238. package/dist/factory-command.test.js.map +0 -1
  239. package/dist/graph/__tests__/attractor-compliance.test.d.ts +0 -10
  240. package/dist/graph/__tests__/attractor-compliance.test.d.ts.map +0 -1
  241. package/dist/graph/__tests__/attractor-compliance.test.js +0 -766
  242. package/dist/graph/__tests__/attractor-compliance.test.js.map +0 -1
  243. package/dist/graph/__tests__/checkpoint.test.d.ts +0 -8
  244. package/dist/graph/__tests__/checkpoint.test.d.ts.map +0 -1
  245. package/dist/graph/__tests__/checkpoint.test.js +0 -329
  246. package/dist/graph/__tests__/checkpoint.test.js.map +0 -1
  247. package/dist/graph/__tests__/condition-parser.test.d.ts +0 -14
  248. package/dist/graph/__tests__/condition-parser.test.d.ts.map +0 -1
  249. package/dist/graph/__tests__/condition-parser.test.js +0 -406
  250. package/dist/graph/__tests__/condition-parser.test.js.map +0 -1
  251. package/dist/graph/__tests__/context.test.d.ts +0 -14
  252. package/dist/graph/__tests__/context.test.d.ts.map +0 -1
  253. package/dist/graph/__tests__/context.test.js +0 -276
  254. package/dist/graph/__tests__/context.test.js.map +0 -1
  255. package/dist/graph/__tests__/edge-selector-events.test.d.ts +0 -11
  256. package/dist/graph/__tests__/edge-selector-events.test.d.ts.map +0 -1
  257. package/dist/graph/__tests__/edge-selector-events.test.js +0 -184
  258. package/dist/graph/__tests__/edge-selector-events.test.js.map +0 -1
  259. package/dist/graph/__tests__/edge-selector.test.d.ts +0 -6
  260. package/dist/graph/__tests__/edge-selector.test.d.ts.map +0 -1
  261. package/dist/graph/__tests__/edge-selector.test.js +0 -452
  262. package/dist/graph/__tests__/edge-selector.test.js.map +0 -1
  263. package/dist/graph/__tests__/executor-convergence.test.d.ts +0 -12
  264. package/dist/graph/__tests__/executor-convergence.test.d.ts.map +0 -1
  265. package/dist/graph/__tests__/executor-convergence.test.js +0 -432
  266. package/dist/graph/__tests__/executor-convergence.test.js.map +0 -1
  267. package/dist/graph/__tests__/executor-fidelity.test.d.ts +0 -13
  268. package/dist/graph/__tests__/executor-fidelity.test.d.ts.map +0 -1
  269. package/dist/graph/__tests__/executor-fidelity.test.js +0 -335
  270. package/dist/graph/__tests__/executor-fidelity.test.js.map +0 -1
  271. package/dist/graph/__tests__/executor.test.d.ts +0 -14
  272. package/dist/graph/__tests__/executor.test.d.ts.map +0 -1
  273. package/dist/graph/__tests__/executor.test.js +0 -901
  274. package/dist/graph/__tests__/executor.test.js.map +0 -1
  275. package/dist/graph/__tests__/fidelity.test.d.ts +0 -8
  276. package/dist/graph/__tests__/fidelity.test.d.ts.map +0 -1
  277. package/dist/graph/__tests__/fidelity.test.js +0 -135
  278. package/dist/graph/__tests__/fidelity.test.js.map +0 -1
  279. package/dist/graph/__tests__/llm-evaluator.test.d.ts +0 -7
  280. package/dist/graph/__tests__/llm-evaluator.test.d.ts.map +0 -1
  281. package/dist/graph/__tests__/llm-evaluator.test.js +0 -106
  282. package/dist/graph/__tests__/llm-evaluator.test.js.map +0 -1
  283. package/dist/graph/__tests__/parser-chaining.test.d.ts +0 -13
  284. package/dist/graph/__tests__/parser-chaining.test.d.ts.map +0 -1
  285. package/dist/graph/__tests__/parser-chaining.test.js +0 -215
  286. package/dist/graph/__tests__/parser-chaining.test.js.map +0 -1
  287. package/dist/graph/__tests__/parser.test.d.ts +0 -22
  288. package/dist/graph/__tests__/parser.test.d.ts.map +0 -1
  289. package/dist/graph/__tests__/parser.test.js +0 -452
  290. package/dist/graph/__tests__/parser.test.js.map +0 -1
  291. package/dist/graph/__tests__/run-state.test.d.ts +0 -13
  292. package/dist/graph/__tests__/run-state.test.d.ts.map +0 -1
  293. package/dist/graph/__tests__/run-state.test.js +0 -189
  294. package/dist/graph/__tests__/run-state.test.js.map +0 -1
  295. package/dist/graph/__tests__/transformer.test.d.ts +0 -16
  296. package/dist/graph/__tests__/transformer.test.d.ts.map +0 -1
  297. package/dist/graph/__tests__/transformer.test.js +0 -350
  298. package/dist/graph/__tests__/transformer.test.js.map +0 -1
  299. package/dist/graph/__tests__/validator-errors.test.d.ts +0 -15
  300. package/dist/graph/__tests__/validator-errors.test.d.ts.map +0 -1
  301. package/dist/graph/__tests__/validator-errors.test.js +0 -572
  302. package/dist/graph/__tests__/validator-errors.test.js.map +0 -1
  303. package/dist/graph/__tests__/validator-warnings.test.d.ts +0 -15
  304. package/dist/graph/__tests__/validator-warnings.test.d.ts.map +0 -1
  305. package/dist/graph/__tests__/validator-warnings.test.js +0 -363
  306. package/dist/graph/__tests__/validator-warnings.test.js.map +0 -1
  307. package/dist/handlers/__tests__/codergen-handler.test.d.ts +0 -14
  308. package/dist/handlers/__tests__/codergen-handler.test.d.ts.map +0 -1
  309. package/dist/handlers/__tests__/codergen-handler.test.js +0 -442
  310. package/dist/handlers/__tests__/codergen-handler.test.js.map +0 -1
  311. package/dist/handlers/__tests__/fan-in.test.d.ts +0 -14
  312. package/dist/handlers/__tests__/fan-in.test.d.ts.map +0 -1
  313. package/dist/handlers/__tests__/fan-in.test.js +0 -399
  314. package/dist/handlers/__tests__/fan-in.test.js.map +0 -1
  315. package/dist/handlers/__tests__/join-policy.test.d.ts +0 -9
  316. package/dist/handlers/__tests__/join-policy.test.d.ts.map +0 -1
  317. package/dist/handlers/__tests__/join-policy.test.js +0 -201
  318. package/dist/handlers/__tests__/join-policy.test.js.map +0 -1
  319. package/dist/handlers/__tests__/manager-loop.test.d.ts +0 -14
  320. package/dist/handlers/__tests__/manager-loop.test.d.ts.map +0 -1
  321. package/dist/handlers/__tests__/manager-loop.test.js +0 -322
  322. package/dist/handlers/__tests__/manager-loop.test.js.map +0 -1
  323. package/dist/handlers/__tests__/parallel-events.test.d.ts +0 -12
  324. package/dist/handlers/__tests__/parallel-events.test.d.ts.map +0 -1
  325. package/dist/handlers/__tests__/parallel-events.test.js +0 -252
  326. package/dist/handlers/__tests__/parallel-events.test.js.map +0 -1
  327. package/dist/handlers/__tests__/parallel-handler.test.d.ts +0 -14
  328. package/dist/handlers/__tests__/parallel-handler.test.d.ts.map +0 -1
  329. package/dist/handlers/__tests__/parallel-handler.test.js +0 -337
  330. package/dist/handlers/__tests__/parallel-handler.test.js.map +0 -1
  331. package/dist/handlers/__tests__/parallel-join.test.d.ts +0 -9
  332. package/dist/handlers/__tests__/parallel-join.test.d.ts.map +0 -1
  333. package/dist/handlers/__tests__/parallel-join.test.js +0 -267
  334. package/dist/handlers/__tests__/parallel-join.test.js.map +0 -1
  335. package/dist/handlers/__tests__/registry.test.d.ts +0 -14
  336. package/dist/handlers/__tests__/registry.test.d.ts.map +0 -1
  337. package/dist/handlers/__tests__/registry.test.js +0 -315
  338. package/dist/handlers/__tests__/registry.test.js.map +0 -1
  339. package/dist/handlers/__tests__/subgraph-events.test.d.ts +0 -10
  340. package/dist/handlers/__tests__/subgraph-events.test.d.ts.map +0 -1
  341. package/dist/handlers/__tests__/subgraph-events.test.js +0 -189
  342. package/dist/handlers/__tests__/subgraph-events.test.js.map +0 -1
  343. package/dist/handlers/__tests__/subgraph-inheritance.test.d.ts +0 -14
  344. package/dist/handlers/__tests__/subgraph-inheritance.test.d.ts.map +0 -1
  345. package/dist/handlers/__tests__/subgraph-inheritance.test.js +0 -267
  346. package/dist/handlers/__tests__/subgraph-inheritance.test.js.map +0 -1
  347. package/dist/handlers/__tests__/subgraph.test.d.ts +0 -14
  348. package/dist/handlers/__tests__/subgraph.test.d.ts.map +0 -1
  349. package/dist/handlers/__tests__/subgraph.test.js +0 -369
  350. package/dist/handlers/__tests__/subgraph.test.js.map +0 -1
  351. package/dist/handlers/__tests__/tool-handler.test.d.ts +0 -11
  352. package/dist/handlers/__tests__/tool-handler.test.d.ts.map +0 -1
  353. package/dist/handlers/__tests__/tool-handler.test.js +0 -184
  354. package/dist/handlers/__tests__/tool-handler.test.js.map +0 -1
  355. package/dist/handlers/__tests__/tool-scenario.test.d.ts +0 -12
  356. package/dist/handlers/__tests__/tool-scenario.test.d.ts.map +0 -1
  357. package/dist/handlers/__tests__/tool-scenario.test.js +0 -222
  358. package/dist/handlers/__tests__/tool-scenario.test.js.map +0 -1
  359. package/dist/handlers/__tests__/wait-human-handler.test.d.ts +0 -11
  360. package/dist/handlers/__tests__/wait-human-handler.test.d.ts.map +0 -1
  361. package/dist/handlers/__tests__/wait-human-handler.test.js +0 -251
  362. package/dist/handlers/__tests__/wait-human-handler.test.js.map +0 -1
  363. package/dist/llm/__tests__/client.test.d.ts +0 -2
  364. package/dist/llm/__tests__/client.test.d.ts.map +0 -1
  365. package/dist/llm/__tests__/client.test.js +0 -198
  366. package/dist/llm/__tests__/client.test.js.map +0 -1
  367. package/dist/llm/__tests__/types.test.d.ts +0 -2
  368. package/dist/llm/__tests__/types.test.d.ts.map +0 -1
  369. package/dist/llm/__tests__/types.test.js +0 -289
  370. package/dist/llm/__tests__/types.test.js.map +0 -1
  371. package/dist/llm/middleware/__tests__/cost-tracking.test.d.ts +0 -2
  372. package/dist/llm/middleware/__tests__/cost-tracking.test.d.ts.map +0 -1
  373. package/dist/llm/middleware/__tests__/cost-tracking.test.js +0 -73
  374. package/dist/llm/middleware/__tests__/cost-tracking.test.js.map +0 -1
  375. package/dist/llm/middleware/__tests__/logging.test.d.ts +0 -2
  376. package/dist/llm/middleware/__tests__/logging.test.d.ts.map +0 -1
  377. package/dist/llm/middleware/__tests__/logging.test.js +0 -127
  378. package/dist/llm/middleware/__tests__/logging.test.js.map +0 -1
  379. package/dist/llm/middleware/__tests__/retry.test.d.ts +0 -2
  380. package/dist/llm/middleware/__tests__/retry.test.d.ts.map +0 -1
  381. package/dist/llm/middleware/__tests__/retry.test.js +0 -126
  382. package/dist/llm/middleware/__tests__/retry.test.js.map +0 -1
  383. package/dist/llm/providers/__tests__/anthropic.test.d.ts +0 -2
  384. package/dist/llm/providers/__tests__/anthropic.test.d.ts.map +0 -1
  385. package/dist/llm/providers/__tests__/anthropic.test.js +0 -412
  386. package/dist/llm/providers/__tests__/anthropic.test.js.map +0 -1
  387. package/dist/llm/providers/__tests__/gemini.test.d.ts +0 -2
  388. package/dist/llm/providers/__tests__/gemini.test.d.ts.map +0 -1
  389. package/dist/llm/providers/__tests__/gemini.test.js +0 -591
  390. package/dist/llm/providers/__tests__/gemini.test.js.map +0 -1
  391. package/dist/llm/providers/__tests__/openai.test.d.ts +0 -2
  392. package/dist/llm/providers/__tests__/openai.test.d.ts.map +0 -1
  393. package/dist/llm/providers/__tests__/openai.test.js +0 -546
  394. package/dist/llm/providers/__tests__/openai.test.js.map +0 -1
  395. package/dist/persistence/__tests__/factory-queries.test.d.ts +0 -9
  396. package/dist/persistence/__tests__/factory-queries.test.d.ts.map +0 -1
  397. package/dist/persistence/__tests__/factory-queries.test.js +0 -372
  398. package/dist/persistence/__tests__/factory-queries.test.js.map +0 -1
  399. package/dist/persistence/__tests__/factory-schema.test.d.ts +0 -6
  400. package/dist/persistence/__tests__/factory-schema.test.d.ts.map +0 -1
  401. package/dist/persistence/__tests__/factory-schema.test.js +0 -105
  402. package/dist/persistence/__tests__/factory-schema.test.js.map +0 -1
  403. package/dist/scenarios/__tests__/cli-command-list.test.d.ts +0 -7
  404. package/dist/scenarios/__tests__/cli-command-list.test.d.ts.map +0 -1
  405. package/dist/scenarios/__tests__/cli-command-list.test.js +0 -237
  406. package/dist/scenarios/__tests__/cli-command-list.test.js.map +0 -1
  407. package/dist/scenarios/__tests__/cli-command.test.d.ts +0 -11
  408. package/dist/scenarios/__tests__/cli-command.test.d.ts.map +0 -1
  409. package/dist/scenarios/__tests__/cli-command.test.js +0 -275
  410. package/dist/scenarios/__tests__/cli-command.test.js.map +0 -1
  411. package/dist/scenarios/__tests__/integrity-pipeline.test.d.ts +0 -15
  412. package/dist/scenarios/__tests__/integrity-pipeline.test.d.ts.map +0 -1
  413. package/dist/scenarios/__tests__/integrity-pipeline.test.js +0 -318
  414. package/dist/scenarios/__tests__/integrity-pipeline.test.js.map +0 -1
  415. package/dist/scenarios/__tests__/runner-twins.test.d.ts +0 -13
  416. package/dist/scenarios/__tests__/runner-twins.test.d.ts.map +0 -1
  417. package/dist/scenarios/__tests__/runner-twins.test.js +0 -205
  418. package/dist/scenarios/__tests__/runner-twins.test.js.map +0 -1
  419. package/dist/scenarios/__tests__/scorer.test.d.ts +0 -11
  420. package/dist/scenarios/__tests__/scorer.test.d.ts.map +0 -1
  421. package/dist/scenarios/__tests__/scorer.test.js +0 -225
  422. package/dist/scenarios/__tests__/scorer.test.js.map +0 -1
  423. package/dist/scenarios/__tests__/scoring-integration.test.d.ts +0 -8
  424. package/dist/scenarios/__tests__/scoring-integration.test.d.ts.map +0 -1
  425. package/dist/scenarios/__tests__/scoring-integration.test.js +0 -178
  426. package/dist/scenarios/__tests__/scoring-integration.test.js.map +0 -1
  427. package/dist/scenarios/__tests__/store.test.d.ts +0 -5
  428. package/dist/scenarios/__tests__/store.test.d.ts.map +0 -1
  429. package/dist/scenarios/__tests__/store.test.js +0 -169
  430. package/dist/scenarios/__tests__/store.test.js.map +0 -1
  431. package/dist/stylesheet/__tests__/stylesheet.test.d.ts +0 -17
  432. package/dist/stylesheet/__tests__/stylesheet.test.d.ts.map +0 -1
  433. package/dist/stylesheet/__tests__/stylesheet.test.js +0 -368
  434. package/dist/stylesheet/__tests__/stylesheet.test.js.map +0 -1
  435. package/dist/templates/__tests__/templates.test.d.ts +0 -7
  436. package/dist/templates/__tests__/templates.test.d.ts.map +0 -1
  437. package/dist/templates/__tests__/templates.test.js +0 -92
  438. package/dist/templates/__tests__/templates.test.js.map +0 -1
  439. package/dist/twins/__tests__/docker-compose.test.d.ts +0 -13
  440. package/dist/twins/__tests__/docker-compose.test.d.ts.map +0 -1
  441. package/dist/twins/__tests__/docker-compose.test.js +0 -247
  442. package/dist/twins/__tests__/docker-compose.test.js.map +0 -1
  443. package/dist/twins/__tests__/health-monitor.test.d.ts +0 -19
  444. package/dist/twins/__tests__/health-monitor.test.d.ts.map +0 -1
  445. package/dist/twins/__tests__/health-monitor.test.js +0 -301
  446. package/dist/twins/__tests__/health-monitor.test.js.map +0 -1
  447. package/dist/twins/__tests__/integration/e2e.test.d.ts +0 -18
  448. package/dist/twins/__tests__/integration/e2e.test.d.ts.map +0 -1
  449. package/dist/twins/__tests__/integration/e2e.test.js +0 -146
  450. package/dist/twins/__tests__/integration/e2e.test.js.map +0 -1
  451. package/dist/twins/__tests__/integration/helpers.d.ts +0 -32
  452. package/dist/twins/__tests__/integration/helpers.d.ts.map +0 -1
  453. package/dist/twins/__tests__/integration/helpers.js +0 -67
  454. package/dist/twins/__tests__/integration/helpers.js.map +0 -1
  455. package/dist/twins/__tests__/integration/lifecycle.test.d.ts +0 -14
  456. package/dist/twins/__tests__/integration/lifecycle.test.d.ts.map +0 -1
  457. package/dist/twins/__tests__/integration/lifecycle.test.js +0 -127
  458. package/dist/twins/__tests__/integration/lifecycle.test.js.map +0 -1
  459. package/dist/twins/__tests__/integration/persistence-integration.test.d.ts +0 -14
  460. package/dist/twins/__tests__/integration/persistence-integration.test.d.ts.map +0 -1
  461. package/dist/twins/__tests__/integration/persistence-integration.test.js +0 -132
  462. package/dist/twins/__tests__/integration/persistence-integration.test.js.map +0 -1
  463. package/dist/twins/__tests__/persistence.test.d.ts +0 -10
  464. package/dist/twins/__tests__/persistence.test.d.ts.map +0 -1
  465. package/dist/twins/__tests__/persistence.test.js +0 -300
  466. package/dist/twins/__tests__/persistence.test.js.map +0 -1
  467. package/dist/twins/__tests__/registry.test.d.ts +0 -7
  468. package/dist/twins/__tests__/registry.test.d.ts.map +0 -1
  469. package/dist/twins/__tests__/registry.test.js +0 -282
  470. package/dist/twins/__tests__/registry.test.js.map +0 -1
  471. package/dist/twins/__tests__/run-state.test.d.ts +0 -9
  472. package/dist/twins/__tests__/run-state.test.d.ts.map +0 -1
  473. package/dist/twins/__tests__/run-state.test.js +0 -112
  474. package/dist/twins/__tests__/run-state.test.js.map +0 -1
  475. package/dist/twins/__tests__/templates-cli.test.d.ts +0 -10
  476. package/dist/twins/__tests__/templates-cli.test.d.ts.map +0 -1
  477. package/dist/twins/__tests__/templates-cli.test.js +0 -187
  478. package/dist/twins/__tests__/templates-cli.test.js.map +0 -1
  479. package/dist/twins/__tests__/templates.test.d.ts +0 -7
  480. package/dist/twins/__tests__/templates.test.d.ts.map +0 -1
  481. package/dist/twins/__tests__/templates.test.js +0 -87
  482. package/dist/twins/__tests__/templates.test.js.map +0 -1
  483. package/dist/twins/__tests__/twins-cli.test.d.ts +0 -11
  484. package/dist/twins/__tests__/twins-cli.test.d.ts.map +0 -1
  485. package/dist/twins/__tests__/twins-cli.test.js +0 -365
  486. package/dist/twins/__tests__/twins-cli.test.js.map +0 -1
@@ -1,300 +0,0 @@
1
- /**
2
- * Unit tests for twin persistence — twin_runs, twin_health_failures tables and
3
- * the TwinPersistenceCoordinator.
4
- *
5
- * Story 47-7, Tasks 1–7.
6
- *
7
- * All tests use createDatabaseAdapter({ backend: 'memory' }) — no Dolt, no Docker, no network.
8
- */
9
- import { describe, it, expect, beforeEach } from 'vitest';
10
- import { createDatabaseAdapter, TypedEventBusImpl } from '@substrate-ai/core';
11
- import { factorySchema } from '../../persistence/factory-schema.js';
12
- import { insertTwinRun, updateTwinRun, recordTwinHealthFailure, getTwinRunsForRun, TwinPersistenceCoordinator, createTwinPersistenceCoordinator, } from '../persistence.js';
13
- // ---------------------------------------------------------------------------
14
- // Test setup
15
- // ---------------------------------------------------------------------------
16
- let adapter;
17
- beforeEach(async () => {
18
- adapter = createDatabaseAdapter({ backend: 'memory' });
19
- await factorySchema(adapter);
20
- });
21
- // ---------------------------------------------------------------------------
22
- // AC1: twin_runs table is created by factorySchema
23
- // ---------------------------------------------------------------------------
24
- describe('AC1: twin_runs table', () => {
25
- it('exists after factorySchema — INSERT succeeds', async () => {
26
- await expect(adapter.query("INSERT INTO twin_runs (id, twin_name, started_at, status) VALUES ('t1', 'localstack', '2026-01-01T00:00:00.000Z', 'running')")).resolves.toBeDefined();
27
- });
28
- it('has ports_json column (nullable)', async () => {
29
- await adapter.query("INSERT INTO twin_runs (id, twin_name, started_at, status, ports_json) VALUES ('t2', 'wiremock', '2026-01-01T00:00:00.000Z', 'running', NULL)");
30
- const rows = await adapter.query("SELECT ports_json FROM twin_runs WHERE id = 't2'");
31
- expect(rows[0]?.ports_json).toBeNull();
32
- });
33
- });
34
- // ---------------------------------------------------------------------------
35
- // AC2: twin_health_failures table is created by factorySchema
36
- // ---------------------------------------------------------------------------
37
- describe('AC2: twin_health_failures table', () => {
38
- it('exists after factorySchema — INSERT succeeds', async () => {
39
- await expect(adapter.query("INSERT INTO twin_health_failures (twin_name, checked_at, error_message) VALUES ('localstack', '2026-01-01T00:00:00.000Z', 'connect ECONNREFUSED')")).resolves.toBeDefined();
40
- });
41
- it('supports querying by twin_name via idx_twin_health_failures_twin', async () => {
42
- await adapter.query("INSERT INTO twin_health_failures (twin_name, checked_at, error_message) VALUES ('wiremock', '2026-01-01T00:00:00.000Z', 'timeout')");
43
- const rows = await adapter.query("SELECT error_message FROM twin_health_failures WHERE twin_name = 'wiremock'");
44
- expect(rows).toHaveLength(1);
45
- expect(rows[0]?.error_message).toBe('timeout');
46
- });
47
- });
48
- // ---------------------------------------------------------------------------
49
- // AC1 + AC2: idempotency
50
- // ---------------------------------------------------------------------------
51
- describe('idempotency', () => {
52
- it('calling factorySchema twice does not throw', async () => {
53
- await expect(factorySchema(adapter)).resolves.toBeUndefined();
54
- });
55
- });
56
- // ---------------------------------------------------------------------------
57
- // AC3: insertTwinRun
58
- // ---------------------------------------------------------------------------
59
- describe('AC3: insertTwinRun', () => {
60
- it('inserts a row and returns a valid UUID-format id', async () => {
61
- const id = await insertTwinRun(adapter, {
62
- twin_name: 'localstack',
63
- ports: [{ host: 4566, container: 4566 }],
64
- });
65
- expect(typeof id).toBe('string');
66
- expect(id).toMatch(/^[0-9a-f-]{36}$/);
67
- });
68
- it('serializes ports correctly and row is readable', async () => {
69
- const id = await insertTwinRun(adapter, {
70
- twin_name: 'localstack',
71
- ports: [
72
- { host: 4566, container: 4566 },
73
- { host: 4572, container: 4572 },
74
- ],
75
- });
76
- const rows = await adapter.query('SELECT * FROM twin_runs WHERE id = ?', [id]);
77
- expect(rows).toHaveLength(1);
78
- const row = rows[0];
79
- expect(row.twin_name).toBe('localstack');
80
- expect(row.status).toBe('running');
81
- const ports = JSON.parse(row.ports_json);
82
- expect(ports).toHaveLength(2);
83
- expect(ports[0]?.host).toBe(4566);
84
- expect(ports[1]?.host).toBe(4572);
85
- });
86
- it('stores run_id when provided', async () => {
87
- const id = await insertTwinRun(adapter, {
88
- twin_name: 'wiremock',
89
- ports: [],
90
- run_id: 'factory-run-abc',
91
- });
92
- const rows = await adapter.query('SELECT * FROM twin_runs WHERE id = ?', [id]);
93
- expect(rows[0]?.run_id).toBe('factory-run-abc');
94
- });
95
- it('sets status to running by default', async () => {
96
- const id = await insertTwinRun(adapter, {
97
- twin_name: 'localstack',
98
- ports: [],
99
- });
100
- const rows = await adapter.query('SELECT status FROM twin_runs WHERE id = ?', [id]);
101
- expect(rows[0]?.status).toBe('running');
102
- });
103
- });
104
- // ---------------------------------------------------------------------------
105
- // AC4: updateTwinRun
106
- // ---------------------------------------------------------------------------
107
- describe('AC4: updateTwinRun', () => {
108
- it('sets stopped_at and status on an existing row', async () => {
109
- const id = await insertTwinRun(adapter, {
110
- twin_name: 'localstack',
111
- ports: [],
112
- });
113
- const stoppedAt = '2026-03-23T12:00:00.000Z';
114
- await updateTwinRun(adapter, id, { status: 'stopped', stopped_at: stoppedAt });
115
- const rows = await adapter.query('SELECT * FROM twin_runs WHERE id = ?', [id]);
116
- expect(rows[0]?.status).toBe('stopped');
117
- expect(rows[0]?.stopped_at).toBe(stoppedAt);
118
- });
119
- });
120
- // ---------------------------------------------------------------------------
121
- // AC5: recordTwinHealthFailure
122
- // ---------------------------------------------------------------------------
123
- describe('AC5: recordTwinHealthFailure', () => {
124
- it('inserts a row with checked_at and error_message', async () => {
125
- await recordTwinHealthFailure(adapter, {
126
- twin_name: 'localstack',
127
- run_id: 'run-123',
128
- error_message: 'connect ECONNREFUSED 127.0.0.1:4566',
129
- });
130
- const rows = await adapter.query("SELECT twin_name, error_message, run_id FROM twin_health_failures WHERE twin_name = 'localstack'");
131
- expect(rows).toHaveLength(1);
132
- expect(rows[0]?.twin_name).toBe('localstack');
133
- expect(rows[0]?.error_message).toBe('connect ECONNREFUSED 127.0.0.1:4566');
134
- expect(rows[0]?.run_id).toBe('run-123');
135
- });
136
- it('sets checked_at to current time when not provided', async () => {
137
- const before = new Date().toISOString();
138
- await recordTwinHealthFailure(adapter, {
139
- twin_name: 'wiremock',
140
- error_message: 'timeout',
141
- });
142
- const after = new Date().toISOString();
143
- const rows = await adapter.query("SELECT checked_at FROM twin_health_failures WHERE twin_name = 'wiremock'");
144
- expect(new Date(rows[0]?.checked_at ?? '').getTime()).toBeGreaterThanOrEqual(new Date(before).getTime());
145
- expect(new Date(rows[0]?.checked_at ?? '').getTime()).toBeLessThanOrEqual(new Date(after).getTime());
146
- });
147
- });
148
- // ---------------------------------------------------------------------------
149
- // AC6: getTwinRunsForRun
150
- // ---------------------------------------------------------------------------
151
- describe('AC6: getTwinRunsForRun', () => {
152
- it('returns empty array when run_id has no twins', async () => {
153
- const result = await getTwinRunsForRun(adapter, 'nonexistent-run-id');
154
- expect(result).toEqual([]);
155
- });
156
- it('returns summary with correct health_failure_count', async () => {
157
- const runId = 'run-abc-123';
158
- await insertTwinRun(adapter, {
159
- twin_name: 'localstack',
160
- ports: [{ host: 4566, container: 4566 }],
161
- run_id: runId,
162
- });
163
- // Record 2 health failures
164
- await recordTwinHealthFailure(adapter, {
165
- twin_name: 'localstack',
166
- run_id: runId,
167
- error_message: 'failure 1',
168
- });
169
- await recordTwinHealthFailure(adapter, {
170
- twin_name: 'localstack',
171
- run_id: runId,
172
- error_message: 'failure 2',
173
- });
174
- const summaries = await getTwinRunsForRun(adapter, runId);
175
- expect(summaries).toHaveLength(1);
176
- expect(summaries[0]?.twin_name).toBe('localstack');
177
- expect(summaries[0]?.health_failure_count).toBe(2);
178
- });
179
- it('parses ports_json back to PortMapping[]', async () => {
180
- const runId = 'run-ports-test';
181
- await insertTwinRun(adapter, {
182
- twin_name: 'localstack',
183
- ports: [
184
- { host: 4566, container: 4566 },
185
- { host: 4572, container: 4572 },
186
- ],
187
- run_id: runId,
188
- });
189
- const summaries = await getTwinRunsForRun(adapter, runId);
190
- expect(summaries).toHaveLength(1);
191
- const ports = summaries[0].ports;
192
- expect(ports).toHaveLength(2);
193
- expect(ports[0]).toEqual({ host: 4566, container: 4566 });
194
- expect(ports[1]).toEqual({ host: 4572, container: 4572 });
195
- });
196
- it('returns empty ports array when ports_json is null', async () => {
197
- const runId = 'run-no-ports';
198
- // Insert directly with null ports_json
199
- await adapter.query("INSERT INTO twin_runs (id, run_id, twin_name, started_at, status) VALUES ('no-ports-id', ?, 'no-ports-twin', '2026-01-01T00:00:00.000Z', 'running')", [runId]);
200
- const summaries = await getTwinRunsForRun(adapter, runId);
201
- expect(summaries[0]?.ports).toEqual([]);
202
- });
203
- it('returns health_failure_count=0 when no failures recorded', async () => {
204
- const runId = 'run-no-failures';
205
- await insertTwinRun(adapter, {
206
- twin_name: 'wiremock',
207
- ports: [],
208
- run_id: runId,
209
- });
210
- const summaries = await getTwinRunsForRun(adapter, runId);
211
- expect(summaries[0]?.health_failure_count).toBe(0);
212
- });
213
- });
214
- // ---------------------------------------------------------------------------
215
- // AC7: TwinPersistenceCoordinator
216
- // ---------------------------------------------------------------------------
217
- /**
218
- * Poll the DB until predicate returns true, up to maxAttempts * intervalMs.
219
- * This provides deterministic synchronization for async event-bus handlers that
220
- * fire void Promise chains — avoiding fragile fixed-delay timeouts.
221
- */
222
- async function pollUntil(predicate, maxAttempts = 100, intervalMs = 1) {
223
- for (let i = 0; i < maxAttempts; i++) {
224
- if (await predicate())
225
- return;
226
- await new Promise((r) => setTimeout(r, intervalMs));
227
- }
228
- throw new Error('pollUntil: timed out waiting for condition');
229
- }
230
- describe('AC7: TwinPersistenceCoordinator', () => {
231
- it('twin:started triggers insertTwinRun — row is present in DB', async () => {
232
- const bus = new TypedEventBusImpl();
233
- new TwinPersistenceCoordinator(adapter, bus);
234
- bus.emit('twin:started', {
235
- twinName: 'localstack',
236
- ports: [{ host: 4566, container: 4566 }],
237
- healthStatus: 'healthy',
238
- runId: 'run-coord-1',
239
- });
240
- // Poll until the row appears — deterministic, no fixed-delay timeout
241
- await pollUntil(async () => {
242
- const rows = await adapter.query("SELECT * FROM twin_runs WHERE twin_name = 'localstack'");
243
- return rows.length > 0;
244
- });
245
- const rows = await adapter.query("SELECT * FROM twin_runs WHERE twin_name = 'localstack'");
246
- expect(rows).toHaveLength(1);
247
- expect(rows[0]?.status).toBe('running');
248
- expect(rows[0]?.run_id).toBe('run-coord-1');
249
- });
250
- it('twin:stopped triggers updateTwinRun — status becomes stopped', async () => {
251
- const bus = new TypedEventBusImpl();
252
- new TwinPersistenceCoordinator(adapter, bus);
253
- bus.emit('twin:started', {
254
- twinName: 'localstack',
255
- ports: [{ host: 4566, container: 4566 }],
256
- healthStatus: 'healthy',
257
- runId: 'run-coord-2',
258
- });
259
- // Poll until insertTwinRun has completed and _rowIds is populated
260
- // (guards against twin:stopped firing before the row id is stored)
261
- await pollUntil(async () => {
262
- const rows = await adapter.query("SELECT * FROM twin_runs WHERE twin_name = 'localstack'");
263
- return rows.length > 0;
264
- });
265
- bus.emit('twin:stopped', { twinName: 'localstack' });
266
- // Poll until updateTwinRun has committed the stopped status
267
- await pollUntil(async () => {
268
- const rows = await adapter.query("SELECT status FROM twin_runs WHERE twin_name = 'localstack'");
269
- return rows[0]?.status === 'stopped';
270
- });
271
- const rows = await adapter.query("SELECT * FROM twin_runs WHERE twin_name = 'localstack'");
272
- expect(rows).toHaveLength(1);
273
- expect(rows[0]?.status).toBe('stopped');
274
- expect(rows[0]?.stopped_at).toBeTruthy();
275
- });
276
- it('twin:health-failed triggers recordTwinHealthFailure (47-7 AC2)', async () => {
277
- const bus = new TypedEventBusImpl();
278
- new TwinPersistenceCoordinator(adapter, bus);
279
- bus.emit('twin:health-failed', {
280
- twinName: 'wiremock',
281
- error: 'connection refused on port 8080',
282
- runId: 'run-health-1',
283
- });
284
- // Poll until the health failure record is persisted
285
- await pollUntil(async () => {
286
- const rows = await adapter.query("SELECT * FROM twin_health_failures WHERE twin_name = 'wiremock'");
287
- return rows.length > 0;
288
- });
289
- const rows = await adapter.query("SELECT * FROM twin_health_failures WHERE twin_name = 'wiremock'");
290
- expect(rows).toHaveLength(1);
291
- expect(rows[0]?.error_message).toBe('connection refused on port 8080');
292
- expect(rows[0]?.run_id).toBe('run-health-1');
293
- });
294
- it('createTwinPersistenceCoordinator factory function returns a coordinator instance', () => {
295
- const bus = new TypedEventBusImpl();
296
- const coordinator = createTwinPersistenceCoordinator(adapter, bus);
297
- expect(coordinator).toBeInstanceOf(TwinPersistenceCoordinator);
298
- });
299
- });
300
- //# sourceMappingURL=persistence.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"persistence.test.js","sourceRoot":"","sources":["../../../src/twins/__tests__/persistence.test.ts"],"names":[],"mappings":"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"}
@@ -1,7 +0,0 @@
1
- /**
2
- * Unit tests for TwinRegistry — discovery, validation, and health polling.
3
- *
4
- * Story 47-1.
5
- */
6
- export {};
7
- //# sourceMappingURL=registry.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry.test.d.ts","sourceRoot":"","sources":["../../../src/twins/__tests__/registry.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -1,282 +0,0 @@
1
- /**
2
- * Unit tests for TwinRegistry — discovery, validation, and health polling.
3
- *
4
- * Story 47-1.
5
- */
6
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
- import { tmpdir } from 'node:os';
8
- import { mkdir, writeFile, rm } from 'node:fs/promises';
9
- import { join } from 'node:path';
10
- import { randomUUID } from 'node:crypto';
11
- import { createTwinRegistry } from '../registry.js';
12
- import { TwinDefinitionError, TwinRegistryError } from '../types.js';
13
- // ---------------------------------------------------------------------------
14
- // Test helpers
15
- // ---------------------------------------------------------------------------
16
- let testDir;
17
- async function writeTwin(dir, filename, content) {
18
- await writeFile(join(dir, filename), content, 'utf-8');
19
- }
20
- // ---------------------------------------------------------------------------
21
- // Setup / teardown
22
- // ---------------------------------------------------------------------------
23
- beforeEach(async () => {
24
- testDir = join(tmpdir(), randomUUID());
25
- await mkdir(testDir, { recursive: true });
26
- });
27
- afterEach(async () => {
28
- await rm(testDir, { recursive: true, force: true });
29
- });
30
- // ---------------------------------------------------------------------------
31
- // AC1: YAML Discovery and Full-Field Parsing
32
- // ---------------------------------------------------------------------------
33
- describe('AC1: YAML discovery and full-field parsing', () => {
34
- it('parses a full-field YAML twin definition correctly', async () => {
35
- await writeTwin(testDir, 'stripe.yaml', `
36
- name: stripe
37
- image: stripe/stripe-mock:latest
38
- ports:
39
- - "12111:12111"
40
- environment:
41
- STRIPE_MOCK_PORT: "12111"
42
- healthcheck:
43
- url: "http://localhost:12111/v1/charges"
44
- interval_ms: 500
45
- timeout_ms: 10000
46
- `);
47
- const registry = createTwinRegistry();
48
- await registry.discover(testDir);
49
- const list = registry.list();
50
- expect(list).toHaveLength(1);
51
- const twin = list[0];
52
- expect(twin.name).toBe('stripe');
53
- expect(twin.image).toBe('stripe/stripe-mock:latest');
54
- expect(twin.ports).toEqual([{ host: 12111, container: 12111 }]);
55
- expect(twin.environment).toEqual({ STRIPE_MOCK_PORT: '12111' });
56
- expect(twin.healthcheck).toEqual({
57
- url: 'http://localhost:12111/v1/charges',
58
- interval_ms: 500,
59
- timeout_ms: 10000,
60
- });
61
- });
62
- it('list() returns exactly one entry matching the file contents', async () => {
63
- await writeTwin(testDir, 'postgres.yaml', `name: postgres\nimage: postgres:16\n`);
64
- const registry = createTwinRegistry();
65
- await registry.discover(testDir);
66
- expect(registry.list()).toHaveLength(1);
67
- expect(registry.list()[0].name).toBe('postgres');
68
- expect(registry.list()[0].image).toBe('postgres:16');
69
- });
70
- it('get() returns the correct definition by name', async () => {
71
- await writeTwin(testDir, 'stripe.yaml', `name: stripe\nimage: stripe/stripe-mock:latest\n`);
72
- const registry = createTwinRegistry();
73
- await registry.discover(testDir);
74
- const twin = registry.get('stripe');
75
- expect(twin).toBeDefined();
76
- expect(twin.name).toBe('stripe');
77
- expect(twin.image).toBe('stripe/stripe-mock:latest');
78
- });
79
- });
80
- // ---------------------------------------------------------------------------
81
- // AC2: Required Field Validation — Descriptive Error on Missing Fields
82
- // ---------------------------------------------------------------------------
83
- describe('AC2: required field validation', () => {
84
- it('throws TwinDefinitionError with file path when "name" is missing', async () => {
85
- await writeTwin(testDir, 'bad.yaml', `image: postgres:16\n`);
86
- const registry = createTwinRegistry();
87
- await expect(registry.discover(testDir)).rejects.toThrow(TwinDefinitionError);
88
- await expect(registry.discover(testDir)).rejects.toThrow(/missing required field: name/);
89
- await expect(registry.discover(testDir)).rejects.toThrow(/bad\.yaml/);
90
- });
91
- it('throws TwinDefinitionError with file path when "image" is missing', async () => {
92
- await writeTwin(testDir, 'bad.yaml', `name: postgres\n`);
93
- const registry = createTwinRegistry();
94
- await expect(registry.discover(testDir)).rejects.toThrow(TwinDefinitionError);
95
- await expect(registry.discover(testDir)).rejects.toThrow(/missing required field: image/);
96
- await expect(registry.discover(testDir)).rejects.toThrow(/bad\.yaml/);
97
- });
98
- });
99
- // ---------------------------------------------------------------------------
100
- // AC3: Malformed YAML and Unknown Field Detection
101
- // ---------------------------------------------------------------------------
102
- describe('AC3: malformed YAML and unknown field detection', () => {
103
- it('throws TwinDefinitionError on syntactically invalid YAML', async () => {
104
- await writeTwin(testDir, 'invalid.yaml', `name: [unclosed bracket\nimage: test:latest\n`);
105
- const registry = createTwinRegistry();
106
- await expect(registry.discover(testDir)).rejects.toThrow(TwinDefinitionError);
107
- await expect(registry.discover(testDir)).rejects.toThrow(/invalid\.yaml/);
108
- });
109
- it('throws TwinDefinitionError on unrecognised top-level field', async () => {
110
- await writeTwin(testDir, 'unknown-field.yaml', `name: test\nimage: test:latest\nunknownField: oops\n`);
111
- const registry = createTwinRegistry();
112
- await expect(registry.discover(testDir)).rejects.toThrow(TwinDefinitionError);
113
- await expect(registry.discover(testDir)).rejects.toThrow(/unknown-field\.yaml/);
114
- });
115
- it('still discovers valid sibling files in the SAME directory when one file is invalid', async () => {
116
- // Both files in the same temp directory: bad.yaml (invalid YAML) and valid.yaml
117
- await writeTwin(testDir, 'bad.yaml', `name: [unclosed`);
118
- await writeTwin(testDir, 'valid.yaml', `name: postgres\nimage: postgres:16\n`);
119
- const registry = createTwinRegistry();
120
- let thrownError;
121
- try {
122
- await registry.discover(testDir);
123
- }
124
- catch (err) {
125
- thrownError = err;
126
- }
127
- // The bad.yaml should cause a TwinDefinitionError to be thrown
128
- expect(thrownError).toBeInstanceOf(TwinDefinitionError);
129
- // The valid sibling in the same directory must still be present in the registry (AC3 fail-soft)
130
- expect(registry.list()).toHaveLength(1);
131
- expect(registry.list()[0].name).toBe('postgres');
132
- });
133
- });
134
- // ---------------------------------------------------------------------------
135
- // AC4: Duplicate Twin Name Detection
136
- // ---------------------------------------------------------------------------
137
- describe('AC4: duplicate twin name detection', () => {
138
- it('throws TwinRegistryError mentioning both file paths when duplicate names are found', async () => {
139
- await writeTwin(testDir, 'postgres-a.yaml', `name: postgres\nimage: postgres:16\n`);
140
- await writeTwin(testDir, 'postgres-b.yaml', `name: postgres\nimage: postgres:15\n`);
141
- const registry = createTwinRegistry();
142
- let thrownError;
143
- try {
144
- await registry.discover(testDir);
145
- }
146
- catch (err) {
147
- thrownError = err;
148
- }
149
- expect(thrownError).toBeDefined();
150
- expect(thrownError).toBeInstanceOf(TwinRegistryError);
151
- expect(thrownError.message).toMatch(/postgres/);
152
- expect(thrownError.message).toMatch(/postgres-a\.yaml/);
153
- expect(thrownError.message).toMatch(/postgres-b\.yaml/);
154
- });
155
- });
156
- // ---------------------------------------------------------------------------
157
- // AC5: Port Mapping Parsed into Structured Objects
158
- // ---------------------------------------------------------------------------
159
- describe('AC5: port mapping parsing', () => {
160
- it('parses "5432:5432" into { host: 5432, container: 5432 }', async () => {
161
- await writeTwin(testDir, 'postgres.yaml', `name: postgres\nimage: postgres:16\nports:\n - "5432:5432"\n`);
162
- const registry = createTwinRegistry();
163
- await registry.discover(testDir);
164
- const twin = registry.get('postgres');
165
- expect(twin.ports).toEqual([{ host: 5432, container: 5432 }]);
166
- });
167
- it('parses multiple port mappings correctly', async () => {
168
- await writeTwin(testDir, 'postgres.yaml', `name: postgres\nimage: postgres:16\nports:\n - "5432:5432"\n - "5433:5433"\n`);
169
- const registry = createTwinRegistry();
170
- await registry.discover(testDir);
171
- const twin = registry.get('postgres');
172
- expect(twin.ports).toHaveLength(2);
173
- expect(twin.ports[0]).toEqual({ host: 5432, container: 5432 });
174
- expect(twin.ports[1]).toEqual({ host: 5433, container: 5433 });
175
- });
176
- });
177
- // ---------------------------------------------------------------------------
178
- // AC6: Optional Fields Default Correctly
179
- // ---------------------------------------------------------------------------
180
- describe('AC6: optional fields default correctly', () => {
181
- it('parses a minimal definition (name + image only) without error', async () => {
182
- await writeTwin(testDir, 'minimal.yaml', `name: minimal\nimage: minimal:latest\n`);
183
- const registry = createTwinRegistry();
184
- await expect(registry.discover(testDir)).resolves.toBeUndefined();
185
- const twin = registry.get('minimal');
186
- expect(twin).toBeDefined();
187
- });
188
- it('applies correct defaults for missing optional fields', async () => {
189
- await writeTwin(testDir, 'minimal.yaml', `name: minimal\nimage: minimal:latest\n`);
190
- const registry = createTwinRegistry();
191
- await registry.discover(testDir);
192
- const twin = registry.get('minimal');
193
- expect(twin.environment).toEqual({});
194
- expect(twin.ports).toEqual([]);
195
- expect(twin.healthcheck).toBeUndefined();
196
- });
197
- });
198
- // ---------------------------------------------------------------------------
199
- // AC7: Health Endpoint Polling
200
- // ---------------------------------------------------------------------------
201
- describe('AC7: health endpoint polling', () => {
202
- it('resolves { healthy: true, attempts: 3 } when mockFetch returns 200 on 3rd call', async () => {
203
- const registry = createTwinRegistry();
204
- const twin = {
205
- name: 'test',
206
- image: 'test:latest',
207
- ports: [],
208
- environment: {},
209
- healthcheck: {
210
- url: 'http://localhost:9999/health',
211
- interval_ms: 10,
212
- timeout_ms: 500,
213
- },
214
- };
215
- let callCount = 0;
216
- const mockFetch = vi.fn().mockImplementation(async () => {
217
- callCount++;
218
- if (callCount < 3)
219
- return { ok: false, status: 503 };
220
- return { ok: true, status: 200 };
221
- });
222
- const result = await registry.pollHealth(twin, { fetch: mockFetch });
223
- expect(result).toEqual({ healthy: true, attempts: 3 });
224
- });
225
- it('resolves { healthy: false, error: "..." } when mockFetch always fails and timeout elapses', async () => {
226
- const registry = createTwinRegistry();
227
- const twin = {
228
- name: 'test',
229
- image: 'test:latest',
230
- ports: [],
231
- environment: {},
232
- healthcheck: {
233
- url: 'http://localhost:9999/health',
234
- interval_ms: 20,
235
- // Wider margin (500ms vs 100ms) avoids flakiness under CI load while keeping the test fast
236
- timeout_ms: 500,
237
- },
238
- };
239
- const mockFetch = vi.fn().mockResolvedValue({ ok: false, status: 503 });
240
- const result = await registry.pollHealth(twin, { fetch: mockFetch });
241
- expect(result).toEqual({
242
- healthy: false,
243
- error: 'Health check timed out after 500ms',
244
- });
245
- });
246
- it('resolves { healthy: true, attempts: 0 } when no healthcheck is defined', async () => {
247
- const registry = createTwinRegistry();
248
- const twin = {
249
- name: 'test',
250
- image: 'test:latest',
251
- ports: [],
252
- environment: {},
253
- // healthcheck is intentionally omitted
254
- };
255
- const result = await registry.pollHealth(twin);
256
- expect(result).toEqual({ healthy: true, attempts: 0 });
257
- });
258
- it('treats network errors (thrown exceptions) as non-2xx and continues polling', async () => {
259
- const registry = createTwinRegistry();
260
- const twin = {
261
- name: 'test',
262
- image: 'test:latest',
263
- ports: [],
264
- environment: {},
265
- healthcheck: {
266
- url: 'http://localhost:9999/health',
267
- interval_ms: 10,
268
- timeout_ms: 500,
269
- },
270
- };
271
- let callCount = 0;
272
- const mockFetch = vi.fn().mockImplementation(async () => {
273
- callCount++;
274
- if (callCount < 3)
275
- throw new Error('ECONNREFUSED');
276
- return { ok: true, status: 200 };
277
- });
278
- const result = await registry.pollHealth(twin, { fetch: mockFetch });
279
- expect(result).toEqual({ healthy: true, attempts: 3 });
280
- });
281
- });
282
- //# sourceMappingURL=registry.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry.test.js","sourceRoot":"","sources":["../../../src/twins/__tests__/registry.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAGpE,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E,IAAI,OAAe,CAAA;AAEnB,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,QAAgB,EAAE,OAAe;IACrE,MAAM,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;AACxD,CAAC;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,UAAU,CAAC,KAAK,IAAI,EAAE;IACpB,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,CAAA;IACtC,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;AAC3C,CAAC,CAAC,CAAA;AAEF,SAAS,CAAC,KAAK,IAAI,EAAE;IACnB,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;AACrD,CAAC,CAAC,CAAA;AAEF,8EAA8E;AAC9E,6CAA6C;AAC7C,8EAA8E;AAE9E,QAAQ,CAAC,4CAA4C,EAAE,GAAG,EAAE;IAC1D,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,SAAS,CACb,OAAO,EACP,aAAa,EACb;;;;;;;;;;;CAWL,CACI,CAAA;QAED,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,MAAM,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAEhC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAA;QAC5B,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAE5B,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAE,CAAA;QACrB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAChC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAA;QACpD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;QAC/D,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,CAAA;QAC/D,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC;YAC/B,GAAG,EAAE,mCAAmC;YACxC,WAAW,EAAE,GAAG;YAChB,UAAU,EAAE,KAAK;SAClB,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,SAAS,CAAC,OAAO,EAAE,eAAe,EAAE,sCAAsC,CAAC,CAAA;QAEjF,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,MAAM,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAEhC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QACvC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACjD,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IACvD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE,kDAAkD,CAAC,CAAA;QAE3F,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,MAAM,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAEhC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACnC,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAA;QAC1B,MAAM,CAAC,IAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACjC,MAAM,CAAC,IAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAA;IACvD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,8EAA8E;AAC9E,uEAAuE;AACvE,8EAA8E;AAE9E,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,sBAAsB,CAAC,CAAA;QAE5D,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAA;QAC7E,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAA;QACxF,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IACvE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACjF,MAAM,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAA;QAExD,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAA;QAC7E,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAA;QACzF,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IACvE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,8EAA8E;AAC9E,kDAAkD;AAClD,8EAA8E;AAE9E,QAAQ,CAAC,iDAAiD,EAAE,GAAG,EAAE;IAC/D,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,+CAA+C,CAAC,CAAA;QAEzF,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAA;QAC7E,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,SAAS,CACb,OAAO,EACP,oBAAoB,EACpB,sDAAsD,CACvD,CAAA;QAED,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAA;QAC7E,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAA;IACjF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;QAClG,gFAAgF;QAChF,MAAM,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAA;QACvD,MAAM,SAAS,CAAC,OAAO,EAAE,YAAY,EAAE,sCAAsC,CAAC,CAAA;QAE9E,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,IAAI,WAA8B,CAAA;QAClC,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAClC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,GAAG,GAAY,CAAA;QAC5B,CAAC;QAED,+DAA+D;QAC/D,MAAM,CAAC,WAAW,CAAC,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAA;QAEvD,gGAAgG;QAChG,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QACvC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,8EAA8E;AAC9E,qCAAqC;AACrC,8EAA8E;AAE9E,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClD,EAAE,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;QAClG,MAAM,SAAS,CAAC,OAAO,EAAE,iBAAiB,EAAE,sCAAsC,CAAC,CAAA;QACnF,MAAM,SAAS,CAAC,OAAO,EAAE,iBAAiB,EAAE,sCAAsC,CAAC,CAAA;QAEnF,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,IAAI,WAA8B,CAAA;QAClC,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAClC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,GAAG,GAAY,CAAA;QAC5B,CAAC;QAED,MAAM,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAA;QACjC,MAAM,CAAC,WAAW,CAAC,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAA;QACrD,MAAM,CAAC,WAAY,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;QAChD,MAAM,CAAC,WAAY,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAA;QACxD,MAAM,CAAC,WAAY,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAA;IAC1D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,8EAA8E;AAC9E,mDAAmD;AACnD,8EAA8E;AAE9E,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,SAAS,CACb,OAAO,EACP,eAAe,EACf,+DAA+D,CAChE,CAAA;QAED,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,MAAM,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAEhC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAE,CAAA;QACtC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAC/D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,SAAS,CACb,OAAO,EACP,eAAe,EACf,gFAAgF,CACjF,CAAA;QAED,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,MAAM,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAEhC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAE,CAAA;QACtC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAClC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC9D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAChE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,8EAA8E;AAC9E,yCAAyC;AACzC,8EAA8E;AAE9E,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;IACtD,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,MAAM,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,wCAAwC,CAAC,CAAA;QAElF,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAA;QAEjE,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QACpC,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAA;IAC5B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,wCAAwC,CAAC,CAAA;QAElF,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,MAAM,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAEhC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAE,CAAA;QACrC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QACpC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAC9B,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,aAAa,EAAE,CAAA;IAC1C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,8EAA8E;AAC9E,+BAA+B;AAC/B,8EAA8E;AAE9E,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,EAAE,CAAC,gFAAgF,EAAE,KAAK,IAAI,EAAE;QAC9F,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,MAAM,IAAI,GAAmB;YAC3B,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,aAAa;YACpB,KAAK,EAAE,EAAE;YACT,WAAW,EAAE,EAAE;YACf,WAAW,EAAE;gBACX,GAAG,EAAE,8BAA8B;gBACnC,WAAW,EAAE,EAAE;gBACf,UAAU,EAAE,GAAG;aAChB;SACF,CAAA;QAED,IAAI,SAAS,GAAG,CAAC,CAAA;QACjB,MAAM,SAAS,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,KAAK,IAAI,EAAE;YACtD,SAAS,EAAE,CAAA;YACX,IAAI,SAAS,GAAG,CAAC;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAA;YACpD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAA;QAClC,CAAC,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,SAAoC,EAAE,CAAC,CAAA;QAC/F,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2FAA2F,EAAE,KAAK,IAAI,EAAE;QACzG,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,MAAM,IAAI,GAAmB;YAC3B,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,aAAa;YACpB,KAAK,EAAE,EAAE;YACT,WAAW,EAAE,EAAE;YACf,WAAW,EAAE;gBACX,GAAG,EAAE,8BAA8B;gBACnC,WAAW,EAAE,EAAE;gBACf,2FAA2F;gBAC3F,UAAU,EAAE,GAAG;aAChB;SACF,CAAA;QAED,MAAM,SAAS,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAEvE,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,SAAoC,EAAE,CAAC,CAAA;QAC/F,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,oCAAoC;SAC5C,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACtF,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,MAAM,IAAI,GAAmB;YAC3B,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,aAAa;YACpB,KAAK,EAAE,EAAE;YACT,WAAW,EAAE,EAAE;YACf,uCAAuC;SACxC,CAAA;QAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;QAC9C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;QAC1F,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,MAAM,IAAI,GAAmB;YAC3B,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,aAAa;YACpB,KAAK,EAAE,EAAE;YACT,WAAW,EAAE,EAAE;YACf,WAAW,EAAE;gBACX,GAAG,EAAE,8BAA8B;gBACnC,WAAW,EAAE,EAAE;gBACf,UAAU,EAAE,GAAG;aAChB;SACF,CAAA;QAED,IAAI,SAAS,GAAG,CAAC,CAAA;QACjB,MAAM,SAAS,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,KAAK,IAAI,EAAE;YACtD,SAAS,EAAE,CAAA;YACX,IAAI,SAAS,GAAG,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAA;YAClD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAA;QAClC,CAAC,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,SAAoC,EAAE,CAAC,CAAA;QAC/F,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -1,9 +0,0 @@
1
- /**
2
- * Unit tests for the run-state helpers.
3
- *
4
- * Mocks `node:fs/promises` to avoid real filesystem I/O.
5
- *
6
- * Story 47-5 — Task 7.
7
- */
8
- export {};
9
- //# sourceMappingURL=run-state.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"run-state.test.d.ts","sourceRoot":"","sources":["../../../src/twins/__tests__/run-state.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}