groundswell 0.0.2 → 1.0.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 (554) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +26 -9
  3. package/dist/cache/cache-key.d.ts +86 -0
  4. package/dist/cache/cache-key.d.ts.map +1 -0
  5. package/dist/cache/cache-key.js +204 -0
  6. package/dist/cache/cache-key.js.map +1 -0
  7. package/dist/cache/cache.d.ts +104 -0
  8. package/dist/cache/cache.d.ts.map +1 -0
  9. package/dist/cache/cache.js +179 -0
  10. package/dist/cache/cache.js.map +1 -0
  11. package/{src/cache/index.ts → dist/cache/index.d.ts} +1 -1
  12. package/dist/cache/index.d.ts.map +1 -0
  13. package/dist/cache/index.js +6 -0
  14. package/dist/cache/index.js.map +1 -0
  15. package/dist/core/agent.d.ts +203 -0
  16. package/dist/core/agent.d.ts.map +1 -0
  17. package/dist/core/agent.js +833 -0
  18. package/dist/core/agent.js.map +1 -0
  19. package/{src/core/context.ts → dist/core/context.d.ts} +16 -67
  20. package/dist/core/context.d.ts.map +1 -0
  21. package/dist/core/context.js +80 -0
  22. package/dist/core/context.js.map +1 -0
  23. package/dist/core/event-tree.d.ts +72 -0
  24. package/dist/core/event-tree.d.ts.map +1 -0
  25. package/dist/core/event-tree.js +211 -0
  26. package/dist/core/event-tree.js.map +1 -0
  27. package/{src/core/factory.ts → dist/core/factory.d.ts} +6 -27
  28. package/dist/core/factory.d.ts.map +1 -0
  29. package/dist/core/factory.js +110 -0
  30. package/dist/core/factory.js.map +1 -0
  31. package/{src/core/index.ts → dist/core/index.d.ts} +2 -10
  32. package/dist/core/index.d.ts.map +1 -0
  33. package/dist/core/index.js +9 -0
  34. package/dist/core/index.js.map +1 -0
  35. package/dist/core/logger.d.ts +50 -0
  36. package/dist/core/logger.d.ts.map +1 -0
  37. package/dist/core/logger.js +91 -0
  38. package/dist/core/logger.js.map +1 -0
  39. package/dist/core/mcp-handler.d.ts +127 -0
  40. package/dist/core/mcp-handler.d.ts.map +1 -0
  41. package/dist/core/mcp-handler.js +323 -0
  42. package/dist/core/mcp-handler.js.map +1 -0
  43. package/dist/core/prompt.d.ts +80 -0
  44. package/dist/core/prompt.d.ts.map +1 -0
  45. package/dist/core/prompt.js +120 -0
  46. package/dist/core/prompt.js.map +1 -0
  47. package/dist/core/workflow-context.d.ts +61 -0
  48. package/dist/core/workflow-context.d.ts.map +1 -0
  49. package/dist/core/workflow-context.js +358 -0
  50. package/dist/core/workflow-context.js.map +1 -0
  51. package/dist/core/workflow.d.ts +543 -0
  52. package/dist/core/workflow.d.ts.map +1 -0
  53. package/dist/core/workflow.js +986 -0
  54. package/dist/core/workflow.js.map +1 -0
  55. package/dist/debugger/event-replayer.d.ts +422 -0
  56. package/dist/debugger/event-replayer.d.ts.map +1 -0
  57. package/dist/debugger/event-replayer.js +639 -0
  58. package/dist/debugger/event-replayer.js.map +1 -0
  59. package/dist/debugger/index.d.ts +2 -0
  60. package/dist/debugger/index.d.ts.map +1 -0
  61. package/{src/debugger/index.ts → dist/debugger/index.js} +1 -0
  62. package/dist/debugger/index.js.map +1 -0
  63. package/dist/debugger/tree-debugger.d.ts +240 -0
  64. package/dist/debugger/tree-debugger.d.ts.map +1 -0
  65. package/dist/debugger/tree-debugger.js +620 -0
  66. package/dist/debugger/tree-debugger.js.map +1 -0
  67. package/dist/decorators/index.d.ts +4 -0
  68. package/dist/decorators/index.d.ts.map +1 -0
  69. package/{src/decorators/index.ts → dist/decorators/index.js} +1 -0
  70. package/dist/decorators/index.js.map +1 -0
  71. package/dist/decorators/observed-state.d.ts +32 -0
  72. package/dist/decorators/observed-state.d.ts.map +1 -0
  73. package/dist/decorators/observed-state.js +79 -0
  74. package/dist/decorators/observed-state.js.map +1 -0
  75. package/dist/decorators/step.d.ts +15 -0
  76. package/dist/decorators/step.d.ts.map +1 -0
  77. package/dist/decorators/step.js +192 -0
  78. package/dist/decorators/step.js.map +1 -0
  79. package/dist/decorators/task.d.ts +50 -0
  80. package/dist/decorators/task.d.ts.map +1 -0
  81. package/dist/decorators/task.js +118 -0
  82. package/dist/decorators/task.js.map +1 -0
  83. package/dist/examples/index.d.ts +3 -0
  84. package/dist/examples/index.d.ts.map +1 -0
  85. package/{src/examples/index.ts → dist/examples/index.js} +1 -0
  86. package/dist/examples/index.js.map +1 -0
  87. package/dist/examples/tdd-orchestrator.d.ts +15 -0
  88. package/dist/examples/tdd-orchestrator.d.ts.map +1 -0
  89. package/dist/examples/tdd-orchestrator.js +121 -0
  90. package/dist/examples/tdd-orchestrator.js.map +1 -0
  91. package/dist/examples/test-cycle-workflow.d.ts +14 -0
  92. package/dist/examples/test-cycle-workflow.d.ts.map +1 -0
  93. package/dist/examples/test-cycle-workflow.js +116 -0
  94. package/dist/examples/test-cycle-workflow.js.map +1 -0
  95. package/dist/harnesses/claude-code-harness.d.ts +391 -0
  96. package/dist/harnesses/claude-code-harness.d.ts.map +1 -0
  97. package/dist/harnesses/claude-code-harness.js +1076 -0
  98. package/dist/harnesses/claude-code-harness.js.map +1 -0
  99. package/dist/harnesses/harness-registry.d.ts +440 -0
  100. package/dist/harnesses/harness-registry.d.ts.map +1 -0
  101. package/dist/harnesses/harness-registry.js +543 -0
  102. package/dist/harnesses/harness-registry.js.map +1 -0
  103. package/dist/harnesses/index.d.ts +12 -0
  104. package/dist/harnesses/index.d.ts.map +1 -0
  105. package/dist/harnesses/index.js +11 -0
  106. package/dist/harnesses/index.js.map +1 -0
  107. package/dist/harnesses/pi-harness.d.ts +219 -0
  108. package/dist/harnesses/pi-harness.d.ts.map +1 -0
  109. package/dist/harnesses/pi-harness.js +676 -0
  110. package/dist/harnesses/pi-harness.js.map +1 -0
  111. package/dist/harnesses/pi-schema-converter.d.ts +24 -0
  112. package/dist/harnesses/pi-schema-converter.d.ts.map +1 -0
  113. package/dist/harnesses/pi-schema-converter.js +81 -0
  114. package/dist/harnesses/pi-schema-converter.js.map +1 -0
  115. package/dist/harnesses/register-defaults.d.ts +24 -0
  116. package/dist/harnesses/register-defaults.d.ts.map +1 -0
  117. package/dist/harnesses/register-defaults.js +40 -0
  118. package/dist/harnesses/register-defaults.js.map +1 -0
  119. package/dist/harnesses/session-store.d.ts +201 -0
  120. package/dist/harnesses/session-store.d.ts.map +1 -0
  121. package/dist/harnesses/session-store.js +254 -0
  122. package/dist/harnesses/session-store.js.map +1 -0
  123. package/dist/index.d.ts +37 -0
  124. package/dist/index.d.ts.map +1 -0
  125. package/dist/index.js +57 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/reflection/index.d.ts +5 -0
  128. package/dist/reflection/index.d.ts.map +1 -0
  129. package/{src/reflection/index.ts → dist/reflection/index.js} +1 -1
  130. package/dist/reflection/index.js.map +1 -0
  131. package/dist/reflection/reflection.d.ts +84 -0
  132. package/dist/reflection/reflection.d.ts.map +1 -0
  133. package/dist/reflection/reflection.js +344 -0
  134. package/dist/reflection/reflection.js.map +1 -0
  135. package/dist/tools/index.d.ts +6 -0
  136. package/dist/tools/index.d.ts.map +1 -0
  137. package/dist/tools/index.js +11 -0
  138. package/dist/tools/index.js.map +1 -0
  139. package/dist/tools/introspection.d.ts +165 -0
  140. package/dist/tools/introspection.d.ts.map +1 -0
  141. package/dist/tools/introspection.js +324 -0
  142. package/dist/tools/introspection.js.map +1 -0
  143. package/dist/types/agent.d.ts +1317 -0
  144. package/dist/types/agent.d.ts.map +1 -0
  145. package/dist/types/agent.js +423 -0
  146. package/dist/types/agent.js.map +1 -0
  147. package/dist/types/decorators.d.ts +40 -0
  148. package/dist/types/decorators.d.ts.map +1 -0
  149. package/dist/types/decorators.js +2 -0
  150. package/dist/types/decorators.js.map +1 -0
  151. package/dist/types/error-strategy.d.ts +13 -0
  152. package/dist/types/error-strategy.d.ts.map +1 -0
  153. package/dist/types/error-strategy.js +2 -0
  154. package/dist/types/error-strategy.js.map +1 -0
  155. package/dist/types/error.d.ts +20 -0
  156. package/dist/types/error.d.ts.map +1 -0
  157. package/dist/types/error.js +2 -0
  158. package/dist/types/error.js.map +1 -0
  159. package/dist/types/events.d.ts +113 -0
  160. package/dist/types/events.d.ts.map +1 -0
  161. package/dist/types/events.js +2 -0
  162. package/dist/types/events.js.map +1 -0
  163. package/dist/types/harnesses.d.ts +474 -0
  164. package/dist/types/harnesses.d.ts.map +1 -0
  165. package/dist/types/harnesses.js +2 -0
  166. package/dist/types/harnesses.js.map +1 -0
  167. package/dist/types/index.d.ts +23 -0
  168. package/dist/types/index.d.ts.map +1 -0
  169. package/dist/types/index.js +8 -0
  170. package/dist/types/index.js.map +1 -0
  171. package/dist/types/logging.d.ts +24 -0
  172. package/dist/types/logging.d.ts.map +1 -0
  173. package/dist/types/logging.js +2 -0
  174. package/dist/types/logging.js.map +1 -0
  175. package/dist/types/observer.d.ts +18 -0
  176. package/dist/types/observer.d.ts.map +1 -0
  177. package/dist/types/observer.js +2 -0
  178. package/dist/types/observer.js.map +1 -0
  179. package/dist/types/prompt.d.ts +31 -0
  180. package/dist/types/prompt.d.ts.map +1 -0
  181. package/dist/types/prompt.js +6 -0
  182. package/dist/types/prompt.js.map +1 -0
  183. package/dist/types/providers.d.ts +691 -0
  184. package/dist/types/providers.d.ts.map +1 -0
  185. package/dist/types/providers.js +14 -0
  186. package/dist/types/providers.js.map +1 -0
  187. package/dist/types/reflection.d.ts +96 -0
  188. package/dist/types/reflection.d.ts.map +1 -0
  189. package/dist/types/reflection.js +24 -0
  190. package/dist/types/reflection.js.map +1 -0
  191. package/dist/types/restart.d.ts +132 -0
  192. package/dist/types/restart.d.ts.map +1 -0
  193. package/dist/types/restart.js +2 -0
  194. package/dist/types/restart.js.map +1 -0
  195. package/dist/types/sdk-primitives.d.ts +118 -0
  196. package/dist/types/sdk-primitives.d.ts.map +1 -0
  197. package/dist/types/sdk-primitives.js +6 -0
  198. package/dist/types/sdk-primitives.js.map +1 -0
  199. package/{src/types/snapshot.ts → dist/types/snapshot.d.ts} +5 -5
  200. package/dist/types/snapshot.d.ts.map +1 -0
  201. package/dist/types/snapshot.js +2 -0
  202. package/dist/types/snapshot.js.map +1 -0
  203. package/dist/types/streaming.d.ts +194 -0
  204. package/dist/types/streaming.d.ts.map +1 -0
  205. package/dist/types/streaming.js +67 -0
  206. package/dist/types/streaming.js.map +1 -0
  207. package/dist/types/workflow-context.d.ts +275 -0
  208. package/dist/types/workflow-context.d.ts.map +1 -0
  209. package/dist/types/workflow-context.js +8 -0
  210. package/dist/types/workflow-context.js.map +1 -0
  211. package/dist/types/workflow.d.ts +30 -0
  212. package/dist/types/workflow.d.ts.map +1 -0
  213. package/dist/types/workflow.js +2 -0
  214. package/dist/types/workflow.js.map +1 -0
  215. package/dist/utils/agent-validation.d.ts +88 -0
  216. package/dist/utils/agent-validation.d.ts.map +1 -0
  217. package/dist/utils/agent-validation.js +87 -0
  218. package/dist/utils/agent-validation.js.map +1 -0
  219. package/dist/utils/delay.d.ts +7 -0
  220. package/dist/utils/delay.d.ts.map +1 -0
  221. package/dist/utils/delay.js +9 -0
  222. package/dist/utils/delay.js.map +1 -0
  223. package/dist/utils/harness-config.d.ts +180 -0
  224. package/dist/utils/harness-config.d.ts.map +1 -0
  225. package/dist/utils/harness-config.js +311 -0
  226. package/dist/utils/harness-config.js.map +1 -0
  227. package/dist/utils/id.d.ts +6 -0
  228. package/dist/utils/id.d.ts.map +1 -0
  229. package/dist/utils/id.js +12 -0
  230. package/dist/utils/id.js.map +1 -0
  231. package/dist/utils/index.d.ts +13 -0
  232. package/dist/utils/index.d.ts.map +1 -0
  233. package/dist/utils/index.js +11 -0
  234. package/dist/utils/index.js.map +1 -0
  235. package/dist/utils/model-spec.d.ts +110 -0
  236. package/dist/utils/model-spec.d.ts.map +1 -0
  237. package/dist/utils/model-spec.js +149 -0
  238. package/dist/utils/model-spec.js.map +1 -0
  239. package/dist/utils/observable.d.ts +54 -0
  240. package/dist/utils/observable.d.ts.map +1 -0
  241. package/dist/utils/observable.js +82 -0
  242. package/dist/utils/observable.js.map +1 -0
  243. package/dist/utils/provider-config.d.ts +10 -0
  244. package/dist/utils/provider-config.d.ts.map +1 -0
  245. package/dist/utils/provider-config.js +10 -0
  246. package/dist/utils/provider-config.js.map +1 -0
  247. package/dist/utils/restart-analysis.d.ts +202 -0
  248. package/dist/utils/restart-analysis.d.ts.map +1 -0
  249. package/dist/utils/restart-analysis.js +426 -0
  250. package/dist/utils/restart-analysis.js.map +1 -0
  251. package/dist/utils/session-serialization.d.ts +118 -0
  252. package/dist/utils/session-serialization.d.ts.map +1 -0
  253. package/dist/utils/session-serialization.js +217 -0
  254. package/dist/utils/session-serialization.js.map +1 -0
  255. package/dist/utils/workflow-error-utils.d.ts +22 -0
  256. package/dist/utils/workflow-error-utils.d.ts.map +1 -0
  257. package/dist/utils/workflow-error-utils.js +45 -0
  258. package/dist/utils/workflow-error-utils.js.map +1 -0
  259. package/package.json +34 -5
  260. package/.claude/commands/subtask-planning/prp-base-create.md +0 -120
  261. package/.claude/commands/subtask-planning/prp-base-execute.md +0 -65
  262. package/.claude/commands/task-breakdown.md +0 -94
  263. package/.claude/settings.local.json +0 -9
  264. package/.claude/system_prompts/task-breakdown.md +0 -101
  265. package/CHANGELOG.md +0 -188
  266. package/PRD.md +0 -543
  267. package/PRPs/001-hierarchical-workflow-engine.md +0 -2438
  268. package/PRPs/PRDs/002-agent-prompt.md +0 -390
  269. package/PRPs/PRDs/003-agent-prompt.md +0 -943
  270. package/PRPs/PRDs/004-agent-prompt.md +0 -1136
  271. package/PRPs/PRDs/tasks-001.json +0 -492
  272. package/PRPs/README.md +0 -83
  273. package/PRPs/templates/prp_base.md +0 -222
  274. package/docs/agent.md +0 -422
  275. package/docs/prompt.md +0 -419
  276. package/docs/workflow.md +0 -600
  277. package/examples/README.md +0 -258
  278. package/examples/examples/01-basic-workflow.ts +0 -100
  279. package/examples/examples/02-decorator-options.ts +0 -217
  280. package/examples/examples/03-parent-child.ts +0 -241
  281. package/examples/examples/04-observers-debugger.ts +0 -340
  282. package/examples/examples/05-error-handling.ts +0 -387
  283. package/examples/examples/06-concurrent-tasks.ts +0 -352
  284. package/examples/examples/07-agent-loops.ts +0 -432
  285. package/examples/examples/08-sdk-features.ts +0 -667
  286. package/examples/examples/09-reflection.ts +0 -573
  287. package/examples/examples/10-introspection.ts +0 -550
  288. package/examples/examples/11-reparenting-workflows.ts +0 -269
  289. package/examples/index.ts +0 -147
  290. package/examples/utils/helpers.ts +0 -57
  291. package/package-lock.json +0 -2398
  292. package/plan/001_d3bb02af4886/TEST_RESULTS.md +0 -259
  293. package/plan/001_d3bb02af4886/backlog.json +0 -867
  294. package/plan/001_d3bb02af4886/bug_fix_tasks.json +0 -484
  295. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S1/PRP.md +0 -488
  296. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S2/PRP.md +0 -581
  297. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S3/PRP.md +0 -687
  298. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S1/PRP.md +0 -492
  299. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/PRP.md +0 -932
  300. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/concurrent_error_testing_patterns.md +0 -1109
  301. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/vitest_concurrent_testing.md +0 -802
  302. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/workflow_engine_test_references.md +0 -603
  303. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S1/PRP.md +0 -564
  304. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S3/PRP.md +0 -518
  305. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S4/PRP.md +0 -1252
  306. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/PRP.md +0 -364
  307. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/CODEBASE_INVENTORY.md +0 -114
  308. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/DECORATOR_DOCUMENTATION_PATTERNS.md +0 -205
  309. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/PRD_LOCATION_ANALYSIS.md +0 -199
  310. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/ULTRATHINK_PRP_PLAN.md +0 -134
  311. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/PRP.md +0 -495
  312. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/research/console_error_inventory.md +0 -435
  313. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S2/PRP.md +0 -506
  314. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S3/PRP.md +0 -612
  315. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/PRP.md +0 -558
  316. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/research/external_research.md +0 -788
  317. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S2/PRP.md +0 -460
  318. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S3/PRP.md +0 -454
  319. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/PRP.md +0 -520
  320. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/RECOMMENDATION.md +0 -417
  321. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/external_workflow_engines_research.md +0 -760
  322. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/security_implications_analysis.md +0 -245
  323. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S2/PRP.md +0 -792
  324. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/PRP.md +0 -535
  325. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/TEST_EXECUTION_REPORT.md +0 -190
  326. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/PRP.md +0 -654
  327. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/TEST_FIX_REPORT.md +0 -227
  328. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/KEY_FINDINGS.md +0 -345
  329. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/QUICK_REFERENCE.md +0 -193
  330. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/test_maintenance_research.md +0 -1323
  331. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/BREAKING_CHANGES_AUDIT.md +0 -1011
  332. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/PRP.md +0 -927
  333. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S2/PRP.md +0 -505
  334. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/architecture/logger_child_signature_analysis.md +0 -401
  335. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/child_implementation_research.md +0 -142
  336. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/test_patterns_research.md +0 -112
  337. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/vitest_patterns_research.md +0 -159
  338. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/PRP.md +0 -549
  339. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/VERIFICATION_REPORT.md +0 -368
  340. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/edge_case_analysis.md +0 -172
  341. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/usage_inventory.md +0 -175
  342. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S2/PRP.md +0 -696
  343. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S4/PRP.md +0 -860
  344. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/PRP.md +0 -1066
  345. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01-testing-aggregated-errors.md +0 -1103
  346. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01_typescript_error_aggregation_patterns.md +0 -789
  347. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02-error-merge-strategy-testing-guide.md +0 -1098
  348. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02_aggregate_error_patterns.md +0 -1037
  349. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03-promise-allsettled-testing-patterns.md +0 -916
  350. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03_error_merging_strategies.md +0 -1045
  351. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/04_github_stackoverflow_examples.md +0 -890
  352. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/05_comprehensive_summary.md +0 -822
  353. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/INDEX.md +0 -668
  354. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/QUICK_REFERENCE.md +0 -706
  355. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/README.md +0 -265
  356. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/RESEARCH_REPORT.md +0 -655
  357. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S4/research/vitest_testing_patterns.md +0 -1103
  358. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T3S2/PRP.md +0 -426
  359. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/PRP.md +0 -506
  360. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/QUICK_REFERENCE.md +0 -114
  361. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/RESEARCH_SUMMARY.md +0 -316
  362. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/vitest_observer_error_logging_best_practices.md +0 -754
  363. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S3/PRP.md +0 -612
  364. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/PRP.md +0 -719
  365. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/README.md +0 -215
  366. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/analysis.md +0 -765
  367. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S3/PRP.md +0 -718
  368. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/DECISION.md +0 -149
  369. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/PRP.md +0 -470
  370. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/ULTRATHINK_PLAN.md +0 -332
  371. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/codebase_workflow_name_analysis.md +0 -167
  372. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/external_best_practices.md +0 -265
  373. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/validation_patterns.md +0 -273
  374. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S1/workflow_engine_ancestry_api_research.md +0 -760
  375. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S3-PRP.md +0 -434
  376. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S1/PRP.md +0 -717
  377. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/PRP.md +0 -472
  378. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/VALIDATION_REPORT.md +0 -125
  379. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/research/ULTRATHINK_PRP_PLAN.md +0 -301
  380. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/error-logging-best-practices.md +0 -1170
  381. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/research_typescript_partial_and_overloads.md +0 -940
  382. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-quick-reference.md +0 -151
  383. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-research.md +0 -650
  384. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/prd_snapshot.md +0 -259
  385. package/plan/001_d3bb02af4886/bugfix/P1M1T1S1/PRP.md +0 -457
  386. package/plan/001_d3bb02af4886/bugfix/RESEARCH_SUMMARY.md +0 -346
  387. package/plan/001_d3bb02af4886/bugfix/architecture/codebase_structure.md +0 -311
  388. package/plan/001_d3bb02af4886/bugfix/architecture/concurrent_execution_best_practices.md +0 -1565
  389. package/plan/001_d3bb02af4886/bugfix/architecture/error_handling_patterns.md +0 -288
  390. package/plan/001_d3bb02af4886/bugfix/architecture/promise_all_analysis.md +0 -741
  391. package/plan/001_d3bb02af4886/docs/PRP/P1M1T1S4-functional-workflow-error-state-capture-test.md +0 -652
  392. package/plan/001_d3bb02af4886/docs/PRP/P1P2-PRP.md +0 -527
  393. package/plan/001_d3bb02af4886/docs/PRP/P3P4-PRP.md +0 -1388
  394. package/plan/001_d3bb02af4886/docs/PRP/P4P5-PRP.md +0 -1136
  395. package/plan/001_d3bb02af4886/docs/PRP/PRP.md +0 -527
  396. package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S1-PRP.md +0 -415
  397. package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S2-PRP.md +0 -378
  398. package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S4-PRP.md +0 -713
  399. package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M2T1S4-PRP.md +0 -370
  400. package/plan/001_d3bb02af4886/docs/PRP_P1M3T1S3.md +0 -499
  401. package/plan/001_d3bb02af4886/docs/TEST_RESULTS.md +0 -230
  402. package/plan/001_d3bb02af4886/docs/architecture/external_deps.md +0 -358
  403. package/plan/001_d3bb02af4886/docs/architecture/system_context.md +0 -242
  404. package/plan/001_d3bb02af4886/docs/bugfix/ANALYSIS_PRD_VS_IMPLEMENTATION.md +0 -1134
  405. package/plan/001_d3bb02af4886/docs/bugfix/GAP_ANALYSIS_SUMMARY.md +0 -179
  406. package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/PRP.md +0 -629
  407. package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/validation-report.md +0 -214
  408. package/plan/001_d3bb02af4886/docs/bugfix/PRP_P1M4T2S3.md +0 -629
  409. package/plan/001_d3bb02af4886/docs/bugfix/bugfix_PRP.md +0 -529
  410. package/plan/001_d3bb02af4886/docs/bugfix/bugfix_QUICK_REFERENCE.md +0 -142
  411. package/plan/001_d3bb02af4886/docs/bugfix/bugfix_README.md +0 -304
  412. package/plan/001_d3bb02af4886/docs/bugfix/bugfix_TEST_RESULTS.md +0 -558
  413. package/plan/001_d3bb02af4886/docs/bugfix/bugfix_VALIDATION_SUMMARY.md +0 -256
  414. package/plan/001_d3bb02af4886/docs/bugfix/system_context.md +0 -346
  415. package/plan/001_d3bb02af4886/docs/bugfix-architecture/bug_analysis.md +0 -415
  416. package/plan/001_d3bb02af4886/docs/bugfix-architecture/implementation_patterns.md +0 -489
  417. package/plan/001_d3bb02af4886/docs/bugfix-architecture/system_context.md +0 -218
  418. package/plan/001_d3bb02af4886/docs/bugfix_INITIATION_SUMMARY.md +0 -380
  419. package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_PATTERNS.md +0 -1923
  420. package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_QUICK_REF.md +0 -319
  421. package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/codebase-context.md +0 -115
  422. package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/cycle-detection-algorithms.md +0 -134
  423. package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/test-patterns.md +0 -153
  424. package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/workflow-class.md +0 -132
  425. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_BEST_PRACTICES.md +0 -716
  426. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_QUICK_REF.md +0 -186
  427. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/GROUNDSWELL_DECORATOR_EXAMPLES.md +0 -604
  428. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/INDEX.md +0 -213
  429. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/codebase_structure.md +0 -30
  430. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/existing_test_pattern.md +0 -56
  431. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/getRootObservers_implementation.md +0 -53
  432. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/test_conventions.md +0 -49
  433. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/PRP.md +0 -958
  434. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/QUICK_REFERENCE.md +0 -339
  435. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/README.md +0 -305
  436. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/SUMMARY.md +0 -433
  437. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/bidirectional-tree-consistency-testing.md +0 -1574
  438. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/test-pattern-examples.md +0 -1014
  439. package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_BEST_PRACTICES.md +0 -1929
  440. package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_CODE_PATTERNS.md +0 -857
  441. package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_INTEGRATION_GUIDE.md +0 -738
  442. package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_RESEARCH_INDEX.md +0 -424
  443. package/plan/001_d3bb02af4886/docs/research/P1P2/REFLECTION_INDEX.md +0 -291
  444. package/plan/001_d3bb02af4886/docs/research/P1P2/REFLECTION_RESEARCH_REPORT.md +0 -1342
  445. package/plan/001_d3bb02af4886/docs/research/P1P2/RESEARCH_SUMMARY.md +0 -342
  446. package/plan/001_d3bb02af4886/docs/research/P1P2/anthropic-sdk.md +0 -174
  447. package/plan/001_d3bb02af4886/docs/research/P1P2/async-local-storage.md +0 -200
  448. package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-code-patterns.md +0 -1205
  449. package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-decision-matrix.md +0 -421
  450. package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-implementation-guide.md +0 -1341
  451. package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-integration-guide.md +0 -834
  452. package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-patterns.md +0 -1468
  453. package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-quick-reference.md +0 -558
  454. package/plan/001_d3bb02af4886/docs/research/P1P2/zod-schema.md +0 -152
  455. package/plan/001_d3bb02af4886/docs/research/P3P4/caching-lru.md +0 -116
  456. package/plan/001_d3bb02af4886/docs/research/P3P4/introspection-tools.md +0 -177
  457. package/plan/001_d3bb02af4886/docs/research/P3P4/reflection-patterns.md +0 -117
  458. package/plan/001_d3bb02af4886/docs/research/P4P5/RESEARCH_SUMMARY.md +0 -151
  459. package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_QUICK_REF.md +0 -376
  460. package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_RESEARCH.md +0 -1507
  461. package/plan/001_d3bb02af4886/docs/research/bugfix_typescript_patterns.md +0 -949
  462. package/plan/001_d3bb02af4886/docs/research/error-testing-research.md +0 -619
  463. package/plan/001_d3bb02af4886/docs/research/error_handling_patterns.md +0 -723
  464. package/plan/001_d3bb02af4886/docs/research/general/INTROSPECTION_RESEARCH_SUMMARY.md +0 -378
  465. package/plan/001_d3bb02af4886/docs/research/general/README-INTROSPECTION.md +0 -352
  466. package/plan/001_d3bb02af4886/docs/research/general/agent-introspection-patterns.md +0 -1085
  467. package/plan/001_d3bb02af4886/docs/research/general/introspection-security-guide.md +0 -984
  468. package/plan/001_d3bb02af4886/docs/research/general/introspection-tool-examples.md +0 -875
  469. package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/PRP_TEMPLATE.md +0 -460
  470. package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/QUICK_REFERENCE.md +0 -324
  471. package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/README.md +0 -175
  472. package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/RESEARCH_REPORT.md +0 -499
  473. package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/SUMMARY.md +0 -163
  474. package/plan/001_d3bb02af4886/prd_snapshot.md +0 -543
  475. package/plan/bugfix/BUG_FIX_SUMMARY.md +0 -961
  476. package/scripts/generate-llms-full.ts +0 -206
  477. package/src/__tests__/adversarial/attachChild-performance.test.ts +0 -216
  478. package/src/__tests__/adversarial/circular-reference.test.ts +0 -101
  479. package/src/__tests__/adversarial/complex-circular-reference.test.ts +0 -139
  480. package/src/__tests__/adversarial/concurrent-task-failures.test.ts +0 -571
  481. package/src/__tests__/adversarial/deep-analysis.test.ts +0 -729
  482. package/src/__tests__/adversarial/deep-hierarchy-stress.test.ts +0 -213
  483. package/src/__tests__/adversarial/e2e-prd-validation.test.ts +0 -448
  484. package/src/__tests__/adversarial/edge-case.test.ts +0 -703
  485. package/src/__tests__/adversarial/error-merge-strategy.test.ts +0 -760
  486. package/src/__tests__/adversarial/incremental-performance.test.ts +0 -140
  487. package/src/__tests__/adversarial/node-map-update-benchmarks.test.ts +0 -457
  488. package/src/__tests__/adversarial/observer-propagation.test.ts +0 -487
  489. package/src/__tests__/adversarial/parent-validation.test.ts +0 -143
  490. package/src/__tests__/adversarial/prd-12-2-compliance.test.ts +0 -611
  491. package/src/__tests__/adversarial/prd-compliance.test.ts +0 -731
  492. package/src/__tests__/compatibility/backward-compatibility.test.ts +0 -1572
  493. package/src/__tests__/helpers/index.ts +0 -18
  494. package/src/__tests__/helpers/tree-verification.ts +0 -257
  495. package/src/__tests__/integration/agent-workflow.test.ts +0 -256
  496. package/src/__tests__/integration/bidirectional-consistency.test.ts +0 -847
  497. package/src/__tests__/integration/observer-logging.test.ts +0 -643
  498. package/src/__tests__/integration/tree-mirroring.test.ts +0 -151
  499. package/src/__tests__/integration/workflow-reparenting.test.ts +0 -303
  500. package/src/__tests__/unit/agent.test.ts +0 -169
  501. package/src/__tests__/unit/cache-key.test.ts +0 -182
  502. package/src/__tests__/unit/cache.test.ts +0 -172
  503. package/src/__tests__/unit/context.test.ts +0 -217
  504. package/src/__tests__/unit/decorators.test.ts +0 -100
  505. package/src/__tests__/unit/introspection-tools.test.ts +0 -277
  506. package/src/__tests__/unit/logger.test.ts +0 -293
  507. package/src/__tests__/unit/observable.test.ts +0 -321
  508. package/src/__tests__/unit/prompt.test.ts +0 -135
  509. package/src/__tests__/unit/reflection.test.ts +0 -210
  510. package/src/__tests__/unit/tree-debugger-incremental.test.ts +0 -170
  511. package/src/__tests__/unit/tree-debugger.test.ts +0 -85
  512. package/src/__tests__/unit/utils/workflow-error-utils.test.ts +0 -209
  513. package/src/__tests__/unit/workflow-detachChild.test.ts +0 -100
  514. package/src/__tests__/unit/workflow-emitEvent-childDetached.test.ts +0 -153
  515. package/src/__tests__/unit/workflow-isDescendantOf.test.ts +0 -180
  516. package/src/__tests__/unit/workflow.test.ts +0 -357
  517. package/src/cache/cache-key.ts +0 -244
  518. package/src/cache/cache.ts +0 -236
  519. package/src/core/agent.ts +0 -593
  520. package/src/core/event-tree.ts +0 -260
  521. package/src/core/logger.ts +0 -112
  522. package/src/core/mcp-handler.ts +0 -184
  523. package/src/core/prompt.ts +0 -150
  524. package/src/core/workflow-context.ts +0 -351
  525. package/src/core/workflow.ts +0 -540
  526. package/src/debugger/tree-debugger.ts +0 -255
  527. package/src/decorators/observed-state.ts +0 -95
  528. package/src/decorators/step.ts +0 -139
  529. package/src/decorators/task.ts +0 -159
  530. package/src/examples/tdd-orchestrator.ts +0 -65
  531. package/src/examples/test-cycle-workflow.ts +0 -64
  532. package/src/index.ts +0 -142
  533. package/src/reflection/reflection.ts +0 -407
  534. package/src/tools/index.ts +0 -36
  535. package/src/tools/introspection.ts +0 -464
  536. package/src/types/agent.ts +0 -90
  537. package/src/types/decorators.ts +0 -32
  538. package/src/types/error-strategy.ts +0 -13
  539. package/src/types/error.ts +0 -20
  540. package/src/types/events.ts +0 -75
  541. package/src/types/index.ts +0 -55
  542. package/src/types/logging.ts +0 -24
  543. package/src/types/observer.ts +0 -18
  544. package/src/types/prompt.ts +0 -40
  545. package/src/types/reflection.ts +0 -117
  546. package/src/types/sdk-primitives.ts +0 -128
  547. package/src/types/workflow-context.ts +0 -163
  548. package/src/types/workflow.ts +0 -37
  549. package/src/utils/id.ts +0 -11
  550. package/src/utils/index.ts +0 -4
  551. package/src/utils/observable.ts +0 -106
  552. package/src/utils/workflow-error-utils.ts +0 -56
  553. package/tsconfig.json +0 -22
  554. package/vitest.config.ts +0 -16
@@ -1,1572 +0,0 @@
1
- /**
2
- * Backward Compatibility Test Suite
3
- *
4
- * Comprehensive tests that validate all existing API usage patterns continue to work
5
- * after bug fixes, and ensures breaking changes fail with clear, actionable error
6
- * messages directing users to the correct migration path.
7
- *
8
- * Related:
9
- * - PRP: P1.M4.T3.S2 - Backward Compatibility Testing
10
- * - Breaking Changes Audit: plan/.../P1M4T3S1/BREAKING_CHANGES_AUDIT.md
11
- *
12
- * Test Coverage:
13
- * 1. Breaking Change: Workflow name validation (LOW severity)
14
- * 2. Backward Compatible: WorkflowLogger.child() string API
15
- * 3. Backward Compatible: Promise.allSettled default behavior
16
- * 4. Documentation Examples: README quick start patterns
17
- * 5. Example Files: All 11 runnable examples
18
- * 6. Decorator Patterns: @Step, @Task, @ObservedState options
19
- * 7. Parent-Child Patterns: Hierarchical workflow creation
20
- */
21
-
22
- import { describe, it, expect } from 'vitest';
23
- import {
24
- Workflow,
25
- WorkflowLogger,
26
- Step,
27
- Task,
28
- ObservedState,
29
- getObservedState,
30
- WorkflowTreeDebugger,
31
- createWorkflow,
32
- WorkflowObserver,
33
- WorkflowEvent,
34
- WorkflowError,
35
- } from '../../index.js';
36
-
37
- // ============================================================================
38
- // Section 1: Breaking Changes - Workflow Name Validation
39
- // ============================================================================
40
- // Severity: LOW
41
- // Impact: Constructor rejects empty/whitespace/long names
42
- // Migration: Provide valid names (simple fix)
43
- // ============================================================================
44
-
45
- describe('Backward Compatibility Tests', () => {
46
- describe('Breaking Changes - Workflow Name Validation', () => {
47
- describe('Class-based constructor pattern', () => {
48
- class TestWorkflow extends Workflow {
49
- constructor(name?: string) {
50
- super(name);
51
- }
52
-
53
- async run(): Promise<string> {
54
- this.setStatus('running');
55
- this.setStatus('completed');
56
- return 'done';
57
- }
58
- }
59
-
60
- it('should throw descriptive error for empty string name', () => {
61
- expect(() => new TestWorkflow(''))
62
- .toThrow('Workflow name cannot be empty or whitespace only');
63
- });
64
-
65
- it('should throw descriptive error for whitespace-only name (spaces)', () => {
66
- expect(() => new TestWorkflow(' '))
67
- .toThrow('Workflow name cannot be empty or whitespace only');
68
- });
69
-
70
- it('should throw descriptive error for whitespace-only name (tabs)', () => {
71
- expect(() => new TestWorkflow('\t\t'))
72
- .toThrow('Workflow name cannot be empty or whitespace only');
73
- });
74
-
75
- it('should throw descriptive error for whitespace-only name (newlines)', () => {
76
- expect(() => new TestWorkflow('\n\n'))
77
- .toThrow('Workflow name cannot be empty or whitespace only');
78
- });
79
-
80
- it('should throw descriptive error for whitespace-only name (mixed)', () => {
81
- expect(() => new TestWorkflow(' \t\n '))
82
- .toThrow('Workflow name cannot be empty or whitespace only');
83
- });
84
-
85
- it('should throw descriptive error for name exceeding 100 characters', () => {
86
- const longName = 'a'.repeat(101);
87
- expect(() => new TestWorkflow(longName))
88
- .toThrow('Workflow name cannot exceed 100 characters');
89
- });
90
-
91
- it('should accept name with exactly 100 characters', () => {
92
- const exactly100 = 'a'.repeat(100);
93
- const wf = new TestWorkflow(exactly100);
94
- expect(wf.getNode().name).toBe(exactly100);
95
- expect(wf.getNode().name.length).toBe(100);
96
- });
97
-
98
- it('should accept valid names with leading/trailing whitespace', () => {
99
- const wf1 = new TestWorkflow(' MyWorkflow ');
100
- expect(wf1.getNode().name).toBe(' MyWorkflow ');
101
-
102
- const wf2 = new TestWorkflow('\tValidName\t');
103
- expect(wf2.getNode().name).toBe('\tValidName\t');
104
- });
105
-
106
- it('should use class name when name is undefined', () => {
107
- const wf = new TestWorkflow();
108
- expect(wf.getNode().name).toBe('TestWorkflow');
109
- });
110
-
111
- it('should use class name when name is null', () => {
112
- const wf = new TestWorkflow(null as any);
113
- expect(wf.getNode().name).toBe('TestWorkflow');
114
- });
115
- });
116
-
117
- describe('Functional constructor pattern', () => {
118
- it('should throw descriptive error for empty string name', () => {
119
- expect(() => new Workflow({ name: '' }, async () => {}))
120
- .toThrow('Workflow name cannot be empty or whitespace only');
121
- });
122
-
123
- it('should throw descriptive error for whitespace name', () => {
124
- expect(() => new Workflow({ name: ' ' }, async () => {}))
125
- .toThrow('Workflow name cannot be empty or whitespace only');
126
- });
127
-
128
- it('should throw descriptive error for name exceeding 100 characters', () => {
129
- const longName = 'a'.repeat(101);
130
- expect(() => new Workflow({ name: longName }, async () => {}))
131
- .toThrow('Workflow name cannot exceed 100 characters');
132
- });
133
-
134
- it('should accept valid name in functional pattern', async () => {
135
- const wf = new Workflow({ name: 'ValidFunctionalWorkflow' }, async () => 'done');
136
- expect(wf.getNode().name).toBe('ValidFunctionalWorkflow');
137
- });
138
- });
139
-
140
- describe('Error message clarity and actionability', () => {
141
- it('should provide clear error message for empty name', () => {
142
- expect(() => new Workflow({ name: '' }, async () => {}))
143
- .toThrow('Workflow name cannot be empty or whitespace only');
144
- });
145
-
146
- it('should provide clear error message for long name', () => {
147
- expect(() => new Workflow({ name: 'a'.repeat(101) }, async () => {}))
148
- .toThrow('Workflow name cannot exceed 100 characters');
149
- });
150
- });
151
- });
152
-
153
- // ============================================================================
154
- // Section 2: Backward Compatible Changes - WorkflowLogger.child()
155
- // ============================================================================
156
- // Change: child() now accepts Partial<LogEntry> in addition to string
157
- // Backward Compatibility: String-based API still works via function overloads
158
- // ============================================================================
159
-
160
- describe('Backward Compatible Changes - WorkflowLogger.child()', () => {
161
- describe('String-based API (backward compatible)', () => {
162
- it('should support string-based logger.child() with parentLogId', async () => {
163
- class TestWorkflow extends Workflow {
164
- async run() {
165
- // Old API - should still work
166
- const childLogger = this.logger.child('parent-log-id');
167
- childLogger.info('Test message');
168
- }
169
- }
170
-
171
- const workflow = new TestWorkflow();
172
- await workflow.run();
173
-
174
- expect(workflow.getNode().logs[0].parentLogId).toBe('parent-log-id');
175
- });
176
-
177
- it('should support string-based logger.child() with all log levels', async () => {
178
- class TestWorkflow extends Workflow {
179
- async run() {
180
- const childLogger = this.logger.child('test-parent');
181
- childLogger.debug('Debug message');
182
- childLogger.info('Info message');
183
- childLogger.warn('Warn message');
184
- childLogger.error('Error message');
185
- }
186
- }
187
-
188
- const workflow = new TestWorkflow();
189
- await workflow.run();
190
-
191
- expect(workflow.getNode().logs.length).toBe(4);
192
- expect(workflow.getNode().logs[0].parentLogId).toBe('test-parent');
193
- expect(workflow.getNode().logs[0].level).toBe('debug');
194
- expect(workflow.getNode().logs[1].level).toBe('info');
195
- expect(workflow.getNode().logs[2].level).toBe('warn');
196
- expect(workflow.getNode().logs[3].level).toBe('error');
197
- });
198
-
199
- it('should support string-based logger.child() with data parameter', async () => {
200
- class TestWorkflow extends Workflow {
201
- async run() {
202
- const childLogger = this.logger.child('data-parent');
203
- childLogger.info('Message with data', { key: 'value', count: 42 });
204
- }
205
- }
206
-
207
- const workflow = new TestWorkflow();
208
- await workflow.run();
209
-
210
- expect(workflow.getNode().logs[0].parentLogId).toBe('data-parent');
211
- expect(workflow.getNode().logs[0].data).toEqual({ key: 'value', count: 42 });
212
- });
213
-
214
- it('should handle empty string (results in undefined parentLogId)', async () => {
215
- class TestWorkflow extends Workflow {
216
- async run() {
217
- const childLogger = this.logger.child('');
218
- childLogger.info('Test message');
219
- }
220
- }
221
-
222
- const workflow = new TestWorkflow();
223
- await workflow.run();
224
-
225
- // Empty string is falsy, so parentLogId becomes undefined
226
- expect(workflow.getNode().logs[0].parentLogId).toBeUndefined();
227
- });
228
- });
229
-
230
- describe('New API - Partial<LogEntry> syntax (also backward compatible)', () => {
231
- it('should support new object-based logger.child() API', async () => {
232
- class TestWorkflow extends Workflow {
233
- async run() {
234
- // New API - should work alongside old API
235
- const childLogger = this.logger.child({ parentLogId: 'parent-log-id' });
236
- childLogger.info('Test message');
237
- }
238
- }
239
-
240
- const workflow = new TestWorkflow();
241
- await workflow.run();
242
-
243
- expect(workflow.getNode().logs[0].parentLogId).toBe('parent-log-id');
244
- });
245
- });
246
-
247
- describe('Parent-child log hierarchy (backward compatible)', () => {
248
- it('should support multi-level nesting with string-based child loggers', async () => {
249
- class TestWorkflow extends Workflow {
250
- async run() {
251
- // Root log
252
- this.logger.info('Root message');
253
- const rootLogId = this.node.logs[0].id;
254
-
255
- // First level child - using string API (backward compatible)
256
- const child1 = this.logger.child(rootLogId);
257
- child1.info('Level 1 child');
258
- const level1LogId = this.node.logs[1].id;
259
-
260
- // Second level child - using string API
261
- const child2 = this.logger.child(level1LogId);
262
- child2.info('Level 2 child');
263
- }
264
- }
265
-
266
- const workflow = new TestWorkflow();
267
- await workflow.run();
268
-
269
- expect(workflow.getNode().logs.length).toBe(3);
270
- expect(workflow.getNode().logs[0].parentLogId).toBeUndefined();
271
- expect(workflow.getNode().logs[1].parentLogId).toBe(workflow.getNode().logs[0].id);
272
- expect(workflow.getNode().logs[2].parentLogId).toBe(workflow.getNode().logs[1].id);
273
- });
274
- });
275
- });
276
-
277
- // ============================================================================
278
- // Section 3: Backward Compatible Changes - Promise.allSettled Default Behavior
279
- // ============================================================================
280
- // Change: @Task with concurrent: true now uses Promise.allSettled()
281
- // Backward Compatibility: Default behavior unchanged - throws first error
282
- // ============================================================================
283
-
284
- describe('Backward Compatible Changes - Promise.allSettled Default Behavior', () => {
285
- // Helper to create a child workflow that may fail
286
- function createChildWorkflow(
287
- parent: Workflow,
288
- name: string,
289
- shouldFail: boolean = false
290
- ): Workflow {
291
- return new (class extends Workflow {
292
- constructor(n: string, p: Workflow) {
293
- super(n, p);
294
- }
295
-
296
- @Step()
297
- async executeStep() {
298
- if (shouldFail) {
299
- throw new Error(`${name} failed`);
300
- }
301
- return `${name} succeeded`;
302
- }
303
-
304
- async run() {
305
- return this.executeStep();
306
- }
307
- })(name, parent);
308
- }
309
-
310
- describe('Default behavior - throws first error (backward compatible)', () => {
311
- it('should throw first error when concurrent task fails', async () => {
312
- class ParentWorkflow extends Workflow {
313
- @Task({ concurrent: true })
314
- async spawnChildren() {
315
- return [
316
- createChildWorkflow(this, 'Child-0', false),
317
- createChildWorkflow(this, 'Child-1', true), // Will fail
318
- createChildWorkflow(this, 'Child-2', false),
319
- createChildWorkflow(this, 'Child-3', false),
320
- ];
321
- }
322
-
323
- async run() {
324
- await this.spawnChildren();
325
- }
326
- }
327
-
328
- const workflow = new ParentWorkflow('Parent');
329
-
330
- // Should throw first error (backward compatible with Promise.all)
331
- await expect(workflow.run()).rejects.toThrow('Child-1 failed');
332
- });
333
-
334
- it('should complete all workflows even when one fails', async () => {
335
- class ParentWorkflow extends Workflow {
336
- @Task({ concurrent: true })
337
- async spawnChildren() {
338
- return [
339
- createChildWorkflow(this, 'Child-0', false),
340
- createChildWorkflow(this, 'Child-1', true), // Will fail
341
- createChildWorkflow(this, 'Child-2', false),
342
- ];
343
- }
344
-
345
- async run() {
346
- try {
347
- await this.spawnChildren();
348
- } catch {
349
- // Expected
350
- }
351
- }
352
- }
353
-
354
- const workflow = new ParentWorkflow('Parent');
355
- await workflow.run();
356
-
357
- // All children should be attached (Promise.allSettled completed all)
358
- expect(workflow.children.length).toBe(3);
359
-
360
- const childNames = workflow.children.map((c) => c.getNode().name);
361
- expect(childNames).toContain('Child-0');
362
- expect(childNames).toContain('Child-1');
363
- expect(childNames).toContain('Child-2');
364
- });
365
- });
366
-
367
- describe('No error merge strategy - default behavior preserved', () => {
368
- it('should not merge errors when errorMergeStrategy is not enabled', async () => {
369
- class ParentWorkflow extends Workflow {
370
- @Task({ concurrent: true })
371
- async spawnChildren() {
372
- return [
373
- createChildWorkflow(this, 'Alpha', true),
374
- createChildWorkflow(this, 'Beta', true),
375
- createChildWorkflow(this, 'Gamma', false),
376
- ];
377
- }
378
-
379
- async run() {
380
- await this.spawnChildren();
381
- }
382
- }
383
-
384
- const workflow = new ParentWorkflow('Parent');
385
-
386
- // Should throw first error only (backward compatible)
387
- await expect(workflow.run()).rejects.toThrow('Alpha failed');
388
- });
389
- });
390
- });
391
-
392
- // ============================================================================
393
- // Section 4: Documentation Examples - README Quick Start
394
- // ============================================================================
395
- // Tests that all README documentation examples execute without modification
396
- // ============================================================================
397
-
398
- describe('Documentation Examples - README Quick Start', () => {
399
- describe('Class-based workflow from README', () => {
400
- it('should execute README class-based workflow example', async () => {
401
- // From README.md lines 22-42 (approximately)
402
- class DataProcessor extends Workflow {
403
- @ObservedState()
404
- progress = 0;
405
-
406
- @Step({ trackTiming: true, snapshotState: true })
407
- async process(): Promise<string[]> {
408
- this.progress = 100;
409
- return ['item1', 'item2', 'item3'];
410
- }
411
-
412
- async run(): Promise<string[]> {
413
- this.setStatus('running');
414
- const result = await this.process();
415
- this.setStatus('completed');
416
- return result;
417
- }
418
- }
419
-
420
- const workflow = new DataProcessor('DataProcessor');
421
- const result = await workflow.run();
422
-
423
- expect(result).toEqual(['item1', 'item2', 'item3']);
424
- expect(workflow.status).toBe('completed');
425
- expect(workflow.progress).toBe(100);
426
- });
427
- });
428
-
429
- describe('Functional workflow from README', () => {
430
- it('should execute README functional workflow example', async () => {
431
- // From README.md lines 44-57 (approximately)
432
- const fetchData = async () => ['data1', 'data2'];
433
- const transform = async (data: string[]) => data.map(x => x.toUpperCase());
434
-
435
- const workflow = createWorkflow(
436
- { name: 'DataPipeline' },
437
- async (ctx) => {
438
- const loaded = await ctx.step('load', async () => fetchData());
439
- const processed = await ctx.step('process', async () => transform(loaded));
440
- return processed;
441
- }
442
- );
443
-
444
- const result = await workflow.run();
445
-
446
- // Result can be either direct value or WorkflowResult object
447
- if (typeof result === 'object' && result !== null && 'data' in result) {
448
- expect(result.data).toEqual(['DATA1', 'DATA2']);
449
- } else {
450
- expect(result).toEqual(['DATA1', 'DATA2']);
451
- }
452
- });
453
- });
454
-
455
- describe('Basic workflow creation pattern', () => {
456
- it('should support basic class extension pattern', async () => {
457
- // From README basic usage
458
- class DataProcessor extends Workflow {
459
- async run(): Promise<string[]> {
460
- this.setStatus('running');
461
- this.logger.info('Processing started');
462
-
463
- const result = await this.processData();
464
-
465
- this.setStatus('completed');
466
- return result;
467
- }
468
-
469
- private async processData(): Promise<string[]> {
470
- return ['item1', 'item2'];
471
- }
472
- }
473
-
474
- const workflow = new DataProcessor('MyProcessor');
475
- const result = await workflow.run();
476
-
477
- expect(result).toEqual(['item1', 'item2']);
478
- expect(workflow.status).toBe('completed');
479
- });
480
- });
481
-
482
- describe('Logger usage from documentation', () => {
483
- it('should support all logger methods from documentation', async () => {
484
- class LoggingWorkflow extends Workflow {
485
- async run(): Promise<void> {
486
- this.setStatus('running');
487
-
488
- // All logger methods from docs
489
- this.logger.debug('Debug message', { data: 'test' });
490
- this.logger.info('Info message');
491
- this.logger.warn('Warning message');
492
- this.logger.error('Error message', { error: new Error('test') });
493
-
494
- this.setStatus('completed');
495
- }
496
- }
497
-
498
- const workflow = new LoggingWorkflow('LoggerTest');
499
- await workflow.run();
500
-
501
- expect(workflow.getNode().logs.length).toBe(4);
502
- expect(workflow.getNode().logs[0].level).toBe('debug');
503
- expect(workflow.getNode().logs[1].level).toBe('info');
504
- expect(workflow.getNode().logs[2].level).toBe('warn');
505
- expect(workflow.getNode().logs[3].level).toBe('error');
506
- });
507
- });
508
- });
509
-
510
- // ============================================================================
511
- // Section 5: Example Files - Core Patterns
512
- // ============================================================================
513
- // Tests that verify example file patterns work correctly
514
- // ============================================================================
515
-
516
- describe('Example Files - Core Patterns', () => {
517
- describe('01-basic-workflow.ts patterns', () => {
518
- it('should support basic workflow with status management', async () => {
519
- // Pattern from examples/examples/01-basic-workflow.ts
520
- class DataProcessingWorkflow extends Workflow {
521
- private data: string[] = [];
522
-
523
- async run(): Promise<string[]> {
524
- this.setStatus('running');
525
- this.logger.info('Starting data processing workflow');
526
-
527
- try {
528
- // Simulate data processing
529
- this.data = ['item1', 'item2', 'item3'];
530
-
531
- this.setStatus('completed');
532
- this.logger.info('Workflow completed successfully');
533
- return this.data;
534
- } catch (error) {
535
- this.setStatus('failed');
536
- this.logger.error('Workflow failed', { error });
537
- throw error;
538
- }
539
- }
540
- }
541
-
542
- const workflow = new DataProcessingWorkflow('DataProcessor');
543
- const result = await workflow.run();
544
-
545
- expect(result).toEqual(['item1', 'item2', 'item3']);
546
- expect(workflow.status).toBe('completed');
547
- });
548
-
549
- it('should support WorkflowTreeDebugger', async () => {
550
- class SimpleWorkflow extends Workflow {
551
- async run(): Promise<string> {
552
- this.setStatus('running');
553
- this.logger.info('Running');
554
- this.setStatus('completed');
555
- return 'done';
556
- }
557
- }
558
-
559
- const workflow = new SimpleWorkflow();
560
- const debugger_ = new WorkflowTreeDebugger(workflow);
561
-
562
- await workflow.run();
563
-
564
- // Debugger should produce valid tree output
565
- const treeString = debugger_.toTreeString();
566
- expect(treeString).toContain('SimpleWorkflow');
567
- });
568
- });
569
-
570
- describe('02-decorator-options.ts patterns', () => {
571
- it('should support @Step with all options', async () => {
572
- // Pattern from examples/examples/02-decorator-options.ts
573
- class StepOptionsWorkflow extends Workflow {
574
- @ObservedState()
575
- currentPhase: string = 'init';
576
-
577
- // Default step - minimal configuration
578
- @Step()
579
- async defaultStep(): Promise<void> {
580
- this.currentPhase = 'default';
581
- }
582
-
583
- // Step with custom name
584
- @Step({ name: 'CustomNamedStep' })
585
- async stepWithCustomName(): Promise<void> {
586
- this.currentPhase = 'custom-named';
587
- }
588
-
589
- // Step with state snapshot
590
- @Step({ snapshotState: true })
591
- async stepWithSnapshot(): Promise<void> {
592
- this.currentPhase = 'snapshot';
593
- }
594
-
595
- // Step with timing tracking
596
- @Step({ trackTiming: true })
597
- async stepWithTiming(): Promise<void> {
598
- this.currentPhase = 'timed';
599
- }
600
-
601
- // Step with start/finish logging
602
- @Step({ logStart: true, logFinish: true })
603
- async stepWithLogging(): Promise<void> {
604
- this.currentPhase = 'logged';
605
- }
606
-
607
- async run(): Promise<void> {
608
- this.setStatus('running');
609
- await this.defaultStep();
610
- await this.stepWithCustomName();
611
- await this.stepWithSnapshot();
612
- await this.stepWithTiming();
613
- await this.stepWithLogging();
614
- this.setStatus('completed');
615
- }
616
- }
617
-
618
- const workflow = new StepOptionsWorkflow();
619
- await workflow.run();
620
-
621
- expect(workflow.status).toBe('completed');
622
- expect(workflow.currentPhase).toBe('logged');
623
- });
624
-
625
- it('should support @ObservedState with redact option', async () => {
626
- // Pattern from examples/examples/02-decorator-options.ts
627
- class StateOptionsWorkflow extends Workflow {
628
- @ObservedState()
629
- publicData: string = 'visible-value';
630
-
631
- @ObservedState({ redact: true })
632
- apiKey: string = 'super-secret-api-key-12345';
633
-
634
- @ObservedState({ hidden: true })
635
- internalCounter: number = 999;
636
-
637
- async run(): Promise<void> {
638
- this.setStatus('running');
639
- this.setStatus('completed');
640
- }
641
- }
642
-
643
- const workflow = new StateOptionsWorkflow();
644
- await workflow.run();
645
-
646
- const snapshot = getObservedState(workflow);
647
-
648
- // Public data should be visible
649
- expect(snapshot.publicData).toBe('visible-value');
650
-
651
- // API key should be redacted
652
- expect(snapshot.apiKey).toBe('***');
653
-
654
- // Hidden field should not be present
655
- expect('internalCounter' in snapshot).toBe(false);
656
- });
657
- });
658
-
659
- describe('03-parent-child.ts patterns', () => {
660
- it('should support hierarchical workflow creation', async () => {
661
- // Pattern from examples/examples/03-parent-child.ts
662
- class LeafWorkflow extends Workflow {
663
- @ObservedState()
664
- processed: boolean = false;
665
-
666
- constructor(name: string, parent?: Workflow) {
667
- super(name, parent);
668
- }
669
-
670
- @Step({ trackTiming: true })
671
- async process(): Promise<void> {
672
- this.logger.info(`Processing ${this.getNode().name}`);
673
- this.processed = true;
674
- }
675
-
676
- async run(): Promise<void> {
677
- this.setStatus('running');
678
- await this.process();
679
- this.setStatus('completed');
680
- }
681
- }
682
-
683
- class ParentWorkflow extends Workflow {
684
- @ObservedState()
685
- itemCount: number = 0;
686
-
687
- @Task()
688
- async spawnChild(name: string): Promise<LeafWorkflow> {
689
- return new LeafWorkflow(name, this);
690
- }
691
-
692
- async run(): Promise<void> {
693
- this.setStatus('running');
694
- this.itemCount = 2;
695
-
696
- const child1 = await this.spawnChild('Child-1');
697
- await child1.run();
698
-
699
- const child2 = await this.spawnChild('Child-2');
700
- await child2.run();
701
-
702
- this.setStatus('completed');
703
- }
704
- }
705
-
706
- const parent = new ParentWorkflow('Parent');
707
- await parent.run();
708
-
709
- expect(parent.status).toBe('completed');
710
- expect(parent.children.length).toBe(2);
711
- expect(parent.itemCount).toBe(2);
712
- });
713
-
714
- it('should support parent parameter in constructor', async () => {
715
- class ChildWorkflow extends Workflow {
716
- constructor(name: string, parent?: Workflow) {
717
- super(name, parent);
718
- }
719
-
720
- async run(): Promise<string> {
721
- this.setStatus('running');
722
- this.setStatus('completed');
723
- return 'child-result';
724
- }
725
- }
726
-
727
- class ParentWorkflow extends Workflow {
728
- @Task()
729
- async createChild(): Promise<ChildWorkflow> {
730
- return new ChildWorkflow('Child', this);
731
- }
732
-
733
- async run(): Promise<void> {
734
- this.setStatus('running');
735
- const child = await this.createChild();
736
- await child.run();
737
- this.setStatus('completed');
738
- }
739
- }
740
-
741
- const parent = new ParentWorkflow('Parent');
742
- await parent.run();
743
-
744
- expect(parent.children.length).toBe(1);
745
- expect(parent.children[0].getNode().name).toBe('Child');
746
- expect(parent.children[0].parent).toBe(parent);
747
- });
748
- });
749
-
750
- describe('05-error-handling.ts patterns', () => {
751
- it('should support @Step with error wrapping', async () => {
752
- // Pattern from examples/examples/05-error-handling.ts
753
- class ErrorDemoWorkflow extends Workflow {
754
- @ObservedState()
755
- currentStep: string = 'init';
756
-
757
- @Step({ snapshotState: true })
758
- async step1(): Promise<void> {
759
- this.currentStep = 'step1';
760
- }
761
-
762
- @Step({ snapshotState: true })
763
- async failingStep(): Promise<void> {
764
- this.currentStep = 'failing';
765
- throw new Error('Something went wrong in failingStep!');
766
- }
767
-
768
- async run(): Promise<void> {
769
- this.setStatus('running');
770
- await this.step1();
771
- await this.failingStep();
772
- this.setStatus('completed');
773
- }
774
- }
775
-
776
- const workflow = new ErrorDemoWorkflow();
777
- let capturedError: WorkflowError | null = null;
778
-
779
- try {
780
- await workflow.run();
781
- } catch (error) {
782
- capturedError = error as WorkflowError;
783
- }
784
-
785
- expect(capturedError).not.toBeNull();
786
- expect(capturedError?.message).toBe('Something went wrong in failingStep!');
787
- expect(capturedError?.state.currentStep).toBe('failing');
788
- expect(capturedError?.workflowId).toBe(workflow.id);
789
- });
790
-
791
- it('should support WorkflowError structure', async () => {
792
- class FailingWorkflow extends Workflow {
793
- @ObservedState()
794
- attempt: number = 1;
795
-
796
- @Step()
797
- async fail(): Promise<void> {
798
- throw new Error('Test failure');
799
- }
800
-
801
- async run(): Promise<void> {
802
- this.setStatus('running');
803
- await this.fail();
804
- }
805
- }
806
-
807
- const workflow = new FailingWorkflow();
808
- let wfError: WorkflowError | null = null;
809
-
810
- try {
811
- await workflow.run();
812
- } catch (error) {
813
- wfError = error as WorkflowError;
814
- }
815
-
816
- expect(wfError).toBeDefined();
817
- expect(wfError?.message).toBe('Test failure');
818
- expect(wfError?.workflowId).toBe(workflow.id);
819
- expect(wfError?.state.attempt).toBe(1);
820
- expect(Array.isArray(wfError?.logs)).toBe(true);
821
- expect(wfError?.stack).toBeDefined();
822
- });
823
- });
824
-
825
- describe('06-concurrent-tasks.ts patterns', () => {
826
- it('should support @Task with concurrent option', async () => {
827
- // Pattern from examples/examples/06-concurrent-tasks.ts
828
- class WorkerWorkflow extends Workflow {
829
- @ObservedState()
830
- result: string = '';
831
-
832
- constructor(id: string, parent?: Workflow) {
833
- super(`Worker-${id}`, parent);
834
- }
835
-
836
- @Step({ trackTiming: true })
837
- async process(): Promise<string> {
838
- this.result = `Result from ${this.getNode().name}`;
839
- return this.result;
840
- }
841
-
842
- async run(): Promise<string> {
843
- this.setStatus('running');
844
- const result = await this.process();
845
- this.setStatus('completed');
846
- return result;
847
- }
848
- }
849
-
850
- class ConcurrentWorkflow extends Workflow {
851
- @ObservedState()
852
- workerCount: number = 0;
853
-
854
- @Task({ concurrent: true })
855
- async createAllWorkers(): Promise<WorkerWorkflow[]> {
856
- this.workerCount = 3;
857
- return [
858
- new WorkerWorkflow('1', this),
859
- new WorkerWorkflow('2', this),
860
- new WorkerWorkflow('3', this),
861
- ];
862
- }
863
-
864
- async run(): Promise<void> {
865
- this.setStatus('running');
866
- await this.createAllWorkers();
867
- this.setStatus('completed');
868
- }
869
- }
870
-
871
- const workflow = new ConcurrentWorkflow();
872
- await workflow.run();
873
-
874
- expect(workflow.status).toBe('completed');
875
- expect(workflow.children.length).toBe(3);
876
- expect(workflow.workerCount).toBe(3);
877
- });
878
-
879
- it('should support manual parallel execution pattern', async () => {
880
- // Manual parallel execution (Promise.all) should still work
881
- class WorkerWorkflow extends Workflow {
882
- async run(): Promise<string> {
883
- this.setStatus('running');
884
- this.setStatus('completed');
885
- return 'worker-result';
886
- }
887
- }
888
-
889
- class ManualParallelWorkflow extends Workflow {
890
- @Task()
891
- async createWorker(): Promise<WorkerWorkflow> {
892
- return new WorkerWorkflow('Worker', this);
893
- }
894
-
895
- async run(): Promise<string[]> {
896
- this.setStatus('running');
897
-
898
- // Manual parallel execution
899
- const workers = await Promise.all([
900
- this.createWorker(),
901
- this.createWorker(),
902
- this.createWorker(),
903
- ]);
904
-
905
- const results = await Promise.all(
906
- workers.map(w => w.run())
907
- );
908
-
909
- this.setStatus('completed');
910
- return results;
911
- }
912
- }
913
-
914
- const workflow = new ManualParallelWorkflow();
915
- const results = await workflow.run();
916
-
917
- expect(results).toEqual(['worker-result', 'worker-result', 'worker-result']);
918
- expect(workflow.children.length).toBe(3);
919
- });
920
- });
921
- });
922
-
923
- // ============================================================================
924
- // Section 6: Decorator Patterns - Comprehensive Coverage
925
- // ============================================================================
926
- // Tests for all decorator option combinations
927
- // ============================================================================
928
-
929
- describe('Decorator Patterns - Comprehensive Coverage', () => {
930
- describe('@Step decorator variations', () => {
931
- it('should support @Step with no options', async () => {
932
- class TestWorkflow extends Workflow {
933
- @Step()
934
- async basicStep(): Promise<void> {
935
- this.logger.info('Basic step');
936
- }
937
-
938
- async run(): Promise<void> {
939
- await this.basicStep();
940
- }
941
- }
942
-
943
- const workflow = new TestWorkflow();
944
- await workflow.run();
945
-
946
- expect(workflow.getNode().logs.some(l => l.message === 'Basic step')).toBe(true);
947
- });
948
-
949
- it('should support @Step with trackTiming option', async () => {
950
- const events: WorkflowEvent[] = [];
951
-
952
- class TestWorkflow extends Workflow {
953
- @Step({ trackTiming: true })
954
- async timedStep(): Promise<void> {
955
- // Do nothing
956
- }
957
-
958
- async run(): Promise<void> {
959
- await this.timedStep();
960
- }
961
- }
962
-
963
- const workflow = new TestWorkflow();
964
- workflow.addObserver({
965
- onLog: () => {},
966
- onEvent: (e) => events.push(e),
967
- onStateUpdated: () => {},
968
- onTreeChanged: () => {},
969
- });
970
-
971
- await workflow.run();
972
-
973
- const stepEndEvents = events.filter(e => e.type === 'stepEnd');
974
- expect(stepEndEvents.length).toBeGreaterThan(0);
975
- if (stepEndEvents[0].type === 'stepEnd') {
976
- expect(stepEndEvents[0].duration).toBeDefined();
977
- }
978
- });
979
-
980
- it('should support @Step with snapshotState option', async () => {
981
- class TestWorkflow extends Workflow {
982
- @ObservedState()
983
- value: number = 0;
984
-
985
- @Step({ snapshotState: true })
986
- async updateStep(): Promise<void> {
987
- this.value = 42;
988
- }
989
-
990
- async run(): Promise<void> {
991
- await this.updateStep();
992
- }
993
- }
994
-
995
- const workflow = new TestWorkflow();
996
- await workflow.run();
997
-
998
- expect(workflow.value).toBe(42);
999
- });
1000
-
1001
- it('should support @Step with logStart and logFinish options', async () => {
1002
- class TestWorkflow extends Workflow {
1003
- @Step({ logStart: true, logFinish: true })
1004
- async loggedStep(): Promise<void> {
1005
- this.logger.info('Inside step');
1006
- }
1007
-
1008
- async run(): Promise<void> {
1009
- await this.loggedStep();
1010
- }
1011
- }
1012
-
1013
- const workflow = new TestWorkflow();
1014
- await workflow.run();
1015
-
1016
- const logs = workflow.getNode().logs;
1017
- expect(logs.some(l => l.message.includes('STEP START'))).toBe(true);
1018
- expect(logs.some(l => l.message.includes('Inside step'))).toBe(true);
1019
- expect(logs.some(l => l.message.includes('STEP END'))).toBe(true);
1020
- });
1021
-
1022
- it('should support @Step with all options combined', async () => {
1023
- class TestWorkflow extends Workflow {
1024
- @ObservedState()
1025
- phase: string = 'init';
1026
-
1027
- @Step({
1028
- name: 'FullyConfigured',
1029
- trackTiming: true,
1030
- snapshotState: true,
1031
- logStart: true,
1032
- logFinish: true,
1033
- })
1034
- async fullStep(): Promise<void> {
1035
- this.phase = 'complete';
1036
- }
1037
-
1038
- async run(): Promise<void> {
1039
- await this.fullStep();
1040
- }
1041
- }
1042
-
1043
- const workflow = new TestWorkflow();
1044
- await workflow.run();
1045
-
1046
- expect(workflow.phase).toBe('complete');
1047
- });
1048
- });
1049
-
1050
- describe('@Task decorator variations', () => {
1051
- it('should support @Task with no options', async () => {
1052
- class ChildWorkflow extends Workflow {
1053
- async run(): Promise<string> {
1054
- return 'child-result';
1055
- }
1056
- }
1057
-
1058
- class ParentWorkflow extends Workflow {
1059
- @Task()
1060
- async createChild(): Promise<ChildWorkflow> {
1061
- return new ChildWorkflow('Child', this);
1062
- }
1063
-
1064
- async run(): Promise<void> {
1065
- const child = await this.createChild();
1066
- await child.run();
1067
- }
1068
- }
1069
-
1070
- const workflow = new ParentWorkflow();
1071
- await workflow.run();
1072
-
1073
- expect(workflow.children.length).toBe(1);
1074
- });
1075
-
1076
- it('should support @Task with custom name', async () => {
1077
- class ChildWorkflow extends Workflow {
1078
- async run(): Promise<string> {
1079
- return 'result';
1080
- }
1081
- }
1082
-
1083
- class ParentWorkflow extends Workflow {
1084
- @Task({ name: 'CustomTaskName' })
1085
- async createChild(): Promise<ChildWorkflow> {
1086
- return new ChildWorkflow('Child', this);
1087
- }
1088
-
1089
- async run(): Promise<void> {
1090
- await this.createChild();
1091
- }
1092
- }
1093
-
1094
- const workflow = new ParentWorkflow();
1095
- const events: WorkflowEvent[] = [];
1096
-
1097
- workflow.addObserver({
1098
- onLog: () => {},
1099
- onEvent: (e) => events.push(e),
1100
- onStateUpdated: () => {},
1101
- onTreeChanged: () => {},
1102
- });
1103
-
1104
- await workflow.run();
1105
-
1106
- const taskEvents = events.filter(e => e.type === 'taskStart' || e.type === 'taskEnd');
1107
- expect(taskEvents.length).toBeGreaterThan(0);
1108
- });
1109
-
1110
- it('should support @Task with concurrent option', async () => {
1111
- class ChildWorkflow extends Workflow {
1112
- async run(): Promise<string> {
1113
- return 'result';
1114
- }
1115
- }
1116
-
1117
- class ParentWorkflow extends Workflow {
1118
- @Task({ concurrent: true })
1119
- async createChildren(): Promise<ChildWorkflow[]> {
1120
- return [
1121
- new ChildWorkflow('Child-1', this),
1122
- new ChildWorkflow('Child-2', this),
1123
- new ChildWorkflow('Child-3', this),
1124
- ];
1125
- }
1126
-
1127
- async run(): Promise<void> {
1128
- await this.createChildren();
1129
- }
1130
- }
1131
-
1132
- const workflow = new ParentWorkflow();
1133
- await workflow.run();
1134
-
1135
- expect(workflow.children.length).toBe(3);
1136
- });
1137
- });
1138
-
1139
- describe('@ObservedState decorator variations', () => {
1140
- it('should support @ObservedState with no options', async () => {
1141
- class TestWorkflow extends Workflow {
1142
- @ObservedState()
1143
- value: number = 0;
1144
-
1145
- async run(): Promise<void> {
1146
- this.value = 42;
1147
- }
1148
- }
1149
-
1150
- const workflow = new TestWorkflow();
1151
- await workflow.run();
1152
-
1153
- const snapshot = getObservedState(workflow);
1154
- expect(snapshot.value).toBe(42);
1155
- });
1156
-
1157
- it('should support @ObservedState with redact option', async () => {
1158
- class TestWorkflow extends Workflow {
1159
- @ObservedState({ redact: true })
1160
- apiKey: string = 'secret-key';
1161
-
1162
- async run(): Promise<void> {
1163
- // Do nothing
1164
- }
1165
- }
1166
-
1167
- const workflow = new TestWorkflow();
1168
- await workflow.run();
1169
-
1170
- const snapshot = getObservedState(workflow);
1171
- expect(snapshot.apiKey).toBe('***');
1172
- });
1173
-
1174
- it('should support @ObservedState with hidden option', async () => {
1175
- class TestWorkflow extends Workflow {
1176
- @ObservedState({ hidden: true })
1177
- internalId: string = 'internal-123';
1178
-
1179
- async run(): Promise<void> {
1180
- // Do nothing
1181
- }
1182
- }
1183
-
1184
- const workflow = new TestWorkflow();
1185
- await workflow.run();
1186
-
1187
- const snapshot = getObservedState(workflow);
1188
- expect('internalId' in snapshot).toBe(false);
1189
- });
1190
-
1191
- it('should support multiple @ObservedState fields', async () => {
1192
- class TestWorkflow extends Workflow {
1193
- @ObservedState()
1194
- field1: string = 'value1';
1195
-
1196
- @ObservedState()
1197
- field2: number = 42;
1198
-
1199
- @ObservedState({ redact: true })
1200
- secret: string = 'hidden';
1201
-
1202
- @ObservedState({ hidden: true })
1203
- internal: string = 'not-visible';
1204
-
1205
- async run(): Promise<void> {
1206
- // Do nothing
1207
- }
1208
- }
1209
-
1210
- const workflow = new TestWorkflow();
1211
- await workflow.run();
1212
-
1213
- const snapshot = getObservedState(workflow);
1214
- expect(snapshot.field1).toBe('value1');
1215
- expect(snapshot.field2).toBe(42);
1216
- expect(snapshot.secret).toBe('***');
1217
- expect('internal' in snapshot).toBe(false);
1218
- });
1219
- });
1220
- });
1221
-
1222
- // ============================================================================
1223
- // Section 7: Parent-Child Patterns - Hierarchical Workflows
1224
- // ============================================================================
1225
- // Tests for parent-child relationship patterns
1226
- // ============================================================================
1227
-
1228
- describe('Parent-Child Patterns - Hierarchical Workflows', () => {
1229
- describe('Constructor-based parent attachment', () => {
1230
- it('should attach child via constructor parent parameter', async () => {
1231
- class ChildWorkflow extends Workflow {
1232
- constructor(name: string, parent?: Workflow) {
1233
- super(name, parent);
1234
- }
1235
-
1236
- async run(): Promise<string> {
1237
- this.setStatus('running');
1238
- this.setStatus('completed');
1239
- return 'child-done';
1240
- }
1241
- }
1242
-
1243
- class ParentWorkflow extends Workflow {
1244
- async run(): Promise<void> {
1245
- this.setStatus('running');
1246
-
1247
- const child1 = new ChildWorkflow('Child1', this);
1248
- await child1.run();
1249
-
1250
- const child2 = new ChildWorkflow('Child2', this);
1251
- await child2.run();
1252
-
1253
- this.setStatus('completed');
1254
- }
1255
- }
1256
-
1257
- const parent = new ParentWorkflow('Parent');
1258
- await parent.run();
1259
-
1260
- expect(parent.children.length).toBe(2);
1261
- expect(parent.children[0].parent).toBe(parent);
1262
- expect(parent.children[1].parent).toBe(parent);
1263
- });
1264
-
1265
- it('should establish bidirectional parent-child relationship', async () => {
1266
- class ChildWorkflow extends Workflow {
1267
- constructor(name: string, parent?: Workflow) {
1268
- super(name, parent);
1269
- }
1270
-
1271
- async run(): Promise<string> {
1272
- return 'done';
1273
- }
1274
- }
1275
-
1276
- class ParentWorkflow extends Workflow {
1277
- @Task()
1278
- async spawnChild(): Promise<ChildWorkflow> {
1279
- return new ChildWorkflow('Child', this);
1280
- }
1281
-
1282
- async run(): Promise<void> {
1283
- const child = await this.spawnChild();
1284
- await child.run();
1285
- }
1286
- }
1287
-
1288
- const parent = new ParentWorkflow('Parent');
1289
- await parent.run();
1290
-
1291
- const child = parent.children[0];
1292
-
1293
- expect(child.parent).toBe(parent);
1294
- expect(parent.children).toContain(child);
1295
- expect(parent.getNode().children).toContain(child.getNode());
1296
- });
1297
- });
1298
-
1299
- describe('Deep hierarchies', () => {
1300
- it('should support multi-level parent-child chains', async () => {
1301
- class Level3Workflow extends Workflow {
1302
- constructor(name: string, parent?: Workflow) {
1303
- super(name, parent);
1304
- }
1305
-
1306
- async run(): Promise<string> {
1307
- this.setStatus('running');
1308
- this.setStatus('completed');
1309
- return 'level3';
1310
- }
1311
- }
1312
-
1313
- class Level2Workflow extends Workflow {
1314
- constructor(name: string, parent?: Workflow) {
1315
- super(name, parent);
1316
- }
1317
-
1318
- @Task()
1319
- async spawnLevel3(): Promise<Level3Workflow> {
1320
- return new Level3Workflow('Level3', this);
1321
- }
1322
-
1323
- async run(): Promise<string> {
1324
- this.setStatus('running');
1325
- const child = await this.spawnLevel3();
1326
- await child.run();
1327
- this.setStatus('completed');
1328
- return 'level2';
1329
- }
1330
- }
1331
-
1332
- class Level1Workflow extends Workflow {
1333
- @Task()
1334
- async spawnLevel2(): Promise<Level2Workflow> {
1335
- return new Level2Workflow('Level2', this);
1336
- }
1337
-
1338
- async run(): Promise<void> {
1339
- this.setStatus('running');
1340
- const child = await this.spawnLevel2();
1341
- await child.run();
1342
- this.setStatus('completed');
1343
- }
1344
- }
1345
-
1346
- const root = new Level1Workflow('Level1');
1347
- await root.run();
1348
-
1349
- expect(root.children.length).toBe(1);
1350
- const level2 = root.children[0];
1351
- expect(level2.children.length).toBe(1);
1352
- const level3 = level2.children[0];
1353
-
1354
- expect(level3.parent).toBe(level2);
1355
- expect(level2.parent).toBe(root);
1356
- });
1357
- });
1358
-
1359
- describe('Sibling workflows', () => {
1360
- it('should support multiple children of same parent', async () => {
1361
- class ChildWorkflow extends Workflow {
1362
- constructor(name: string, parent?: Workflow) {
1363
- super(name, parent);
1364
- }
1365
-
1366
- async run(): Promise<string> {
1367
- return 'done';
1368
- }
1369
- }
1370
-
1371
- class ParentWorkflow extends Workflow {
1372
- @ObservedState()
1373
- childCount: number = 0;
1374
-
1375
- async run(): Promise<void> {
1376
- this.childCount = 3;
1377
-
1378
- for (let i = 1; i <= 3; i++) {
1379
- const child = new ChildWorkflow(`Child${i}`, this);
1380
- await child.run();
1381
- }
1382
- }
1383
- }
1384
-
1385
- const parent = new ParentWorkflow('Parent');
1386
- await parent.run();
1387
-
1388
- expect(parent.children.length).toBe(3);
1389
- expect(parent.childCount).toBe(3);
1390
-
1391
- const childNames = parent.children.map(c => c.getNode().name);
1392
- expect(childNames).toEqual(['Child1', 'Child2', 'Child3']);
1393
- });
1394
- });
1395
- });
1396
-
1397
- // ============================================================================
1398
- // Section 8: Additional Backward Compatibility Validations
1399
- // ============================================================================
1400
- // Additional tests for comprehensive backward compatibility coverage
1401
- // ============================================================================
1402
-
1403
- describe('Additional Backward Compatibility Validations', () => {
1404
- describe('Workflow status transitions', () => {
1405
- it('should support all status transitions from examples', async () => {
1406
- class StatusWorkflow extends Workflow {
1407
- async run(): Promise<void> {
1408
- // idle -> running -> completed
1409
- expect(this.status).toBe('idle');
1410
- this.setStatus('running');
1411
- expect(this.status).toBe('running');
1412
- this.setStatus('completed');
1413
- expect(this.status).toBe('completed');
1414
- }
1415
- }
1416
-
1417
- const workflow = new StatusWorkflow();
1418
- await workflow.run();
1419
-
1420
- expect(workflow.status).toBe('completed');
1421
- });
1422
-
1423
- it('should support failed status transition', async () => {
1424
- class FailingWorkflow extends Workflow {
1425
- async run(): Promise<void> {
1426
- this.setStatus('running');
1427
- this.setStatus('failed');
1428
- throw new Error('Intentional failure');
1429
- }
1430
- }
1431
-
1432
- const workflow = new FailingWorkflow();
1433
-
1434
- try {
1435
- await workflow.run();
1436
- } catch {
1437
- // Expected
1438
- }
1439
-
1440
- expect(workflow.status).toBe('failed');
1441
- });
1442
- });
1443
-
1444
- describe('Workflow ID generation', () => {
1445
- it('should generate unique IDs for each workflow instance', () => {
1446
- class TestWorkflow extends Workflow {}
1447
-
1448
- const wf1 = new TestWorkflow();
1449
- const wf2 = new TestWorkflow();
1450
- const wf3 = new TestWorkflow();
1451
-
1452
- expect(wf1.id).not.toBe(wf2.id);
1453
- expect(wf2.id).not.toBe(wf3.id);
1454
- expect(wf1.id).not.toBe(wf3.id);
1455
- });
1456
- });
1457
-
1458
- describe('Workflow name defaults', () => {
1459
- it('should use class name as default when no name provided', () => {
1460
- class MyCustomWorkflow extends Workflow {}
1461
-
1462
- const wf = new MyCustomWorkflow();
1463
- expect(wf.getNode().name).toBe('MyCustomWorkflow');
1464
- });
1465
- });
1466
-
1467
- describe('Logger child with both APIs', () => {
1468
- it('should support mixing old and new logger.child() APIs', async () => {
1469
- class TestWorkflow extends Workflow {
1470
- async run() {
1471
- // Old API
1472
- const child1 = this.logger.child('log-1');
1473
- child1.info('Message 1');
1474
-
1475
- // New API
1476
- const child2 = this.logger.child({ parentLogId: 'log-2' });
1477
- child2.info('Message 2');
1478
-
1479
- // Old API again
1480
- const child3 = this.logger.child('log-3');
1481
- child3.info('Message 3');
1482
- }
1483
- }
1484
-
1485
- const workflow = new TestWorkflow();
1486
- await workflow.run();
1487
-
1488
- expect(workflow.getNode().logs[0].parentLogId).toBe('log-1');
1489
- expect(workflow.getNode().logs[1].parentLogId).toBe('log-2');
1490
- expect(workflow.getNode().logs[2].parentLogId).toBe('log-3');
1491
- });
1492
- });
1493
-
1494
- describe('WorkflowTreeDebugger compatibility', () => {
1495
- it('should work with WorkflowTreeDebugger', async () => {
1496
- class TestWorkflow extends Workflow {
1497
- @ObservedState()
1498
- value: number = 42;
1499
-
1500
- @Step()
1501
- async testStep(): Promise<void> {
1502
- this.logger.info('Test log');
1503
- }
1504
-
1505
- async run(): Promise<void> {
1506
- this.setStatus('running');
1507
- await this.testStep();
1508
- this.setStatus('completed');
1509
- }
1510
- }
1511
-
1512
- const workflow = new TestWorkflow();
1513
- const debugger_ = new WorkflowTreeDebugger(workflow);
1514
-
1515
- await workflow.run();
1516
-
1517
- // All debugger methods should work
1518
- const tree = debugger_.toTreeString();
1519
- const logs = debugger_.toLogString();
1520
- const stats = debugger_.getStats();
1521
-
1522
- expect(tree).toContain('TestWorkflow');
1523
- expect(typeof logs).toBe('string');
1524
- expect(stats.totalNodes).toBeGreaterThanOrEqual(1);
1525
- });
1526
- });
1527
-
1528
- describe('Observer pattern compatibility', () => {
1529
- it('should support WorkflowObserver with all callbacks', async () => {
1530
- const logs: string[] = [];
1531
- const events: WorkflowEvent[] = [];
1532
- const stateUpdates: number[] = [];
1533
- const treeUpdates: number[] = [];
1534
-
1535
- class TestWorkflow extends Workflow {
1536
- @ObservedState()
1537
- counter: number = 0;
1538
-
1539
- @Step({ snapshotState: true })
1540
- async testStep(): Promise<void> {
1541
- this.counter = 1;
1542
- this.logger.info('Test message');
1543
- }
1544
-
1545
- async run(): Promise<void> {
1546
- this.setStatus('running');
1547
- await this.testStep();
1548
- this.setStatus('completed');
1549
- }
1550
- }
1551
-
1552
- const workflow = new TestWorkflow();
1553
-
1554
- const observer: WorkflowObserver = {
1555
- onLog: (entry) => logs.push(entry.message),
1556
- onEvent: (event) => events.push(event),
1557
- onStateUpdated: () => stateUpdates.push(1),
1558
- onTreeChanged: () => treeUpdates.push(1),
1559
- };
1560
-
1561
- workflow.addObserver(observer);
1562
- await workflow.run();
1563
-
1564
- expect(logs.length).toBeGreaterThan(0);
1565
- expect(logs.some(l => l === 'Test message')).toBe(true);
1566
- expect(events.length).toBeGreaterThan(0);
1567
- expect(stateUpdates.length).toBeGreaterThan(0);
1568
- expect(treeUpdates.length).toBeGreaterThan(0);
1569
- });
1570
- });
1571
- });
1572
- });