groundswell 0.0.1 → 0.0.2

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 (242) hide show
  1. package/.claude/commands/subtask-planning/prp-base-create.md +120 -0
  2. package/.claude/commands/subtask-planning/prp-base-execute.md +65 -0
  3. package/.claude/commands/task-breakdown.md +94 -0
  4. package/.claude/system_prompts/task-breakdown.md +1 -0
  5. package/CHANGELOG.md +188 -0
  6. package/PRD.md +543 -0
  7. package/README.md +99 -5
  8. package/examples/README.md +15 -1
  9. package/examples/examples/11-reparenting-workflows.ts +269 -0
  10. package/examples/index.ts +4 -0
  11. package/package-lock.json +2398 -0
  12. package/package.json +3 -1
  13. package/plan/001_d3bb02af4886/TEST_RESULTS.md +259 -0
  14. package/plan/001_d3bb02af4886/bug_fix_tasks.json +484 -0
  15. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S1/PRP.md +488 -0
  16. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S2/PRP.md +581 -0
  17. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S3/PRP.md +687 -0
  18. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S1/PRP.md +492 -0
  19. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/PRP.md +932 -0
  20. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/concurrent_error_testing_patterns.md +1109 -0
  21. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/vitest_concurrent_testing.md +802 -0
  22. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/workflow_engine_test_references.md +603 -0
  23. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S1/PRP.md +564 -0
  24. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S3/PRP.md +518 -0
  25. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S4/PRP.md +1252 -0
  26. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/PRP.md +364 -0
  27. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/CODEBASE_INVENTORY.md +114 -0
  28. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/DECORATOR_DOCUMENTATION_PATTERNS.md +205 -0
  29. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/PRD_LOCATION_ANALYSIS.md +199 -0
  30. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/ULTRATHINK_PRP_PLAN.md +134 -0
  31. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/PRP.md +495 -0
  32. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/research/console_error_inventory.md +435 -0
  33. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S2/PRP.md +506 -0
  34. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S3/PRP.md +612 -0
  35. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/PRP.md +558 -0
  36. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/research/external_research.md +788 -0
  37. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S2/PRP.md +460 -0
  38. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S3/PRP.md +454 -0
  39. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/PRP.md +520 -0
  40. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/RECOMMENDATION.md +417 -0
  41. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/external_workflow_engines_research.md +760 -0
  42. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/security_implications_analysis.md +245 -0
  43. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S2/PRP.md +792 -0
  44. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/PRP.md +535 -0
  45. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/TEST_EXECUTION_REPORT.md +190 -0
  46. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/PRP.md +654 -0
  47. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/TEST_FIX_REPORT.md +227 -0
  48. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/KEY_FINDINGS.md +345 -0
  49. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/QUICK_REFERENCE.md +193 -0
  50. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/test_maintenance_research.md +1323 -0
  51. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/BREAKING_CHANGES_AUDIT.md +1011 -0
  52. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/PRP.md +927 -0
  53. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S2/PRP.md +505 -0
  54. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/architecture/logger_child_signature_analysis.md +401 -0
  55. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/child_implementation_research.md +142 -0
  56. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/test_patterns_research.md +112 -0
  57. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/vitest_patterns_research.md +159 -0
  58. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/PRP.md +549 -0
  59. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/VERIFICATION_REPORT.md +368 -0
  60. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/edge_case_analysis.md +172 -0
  61. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/usage_inventory.md +175 -0
  62. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S2/PRP.md +696 -0
  63. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S4/PRP.md +860 -0
  64. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/PRP.md +1066 -0
  65. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01-testing-aggregated-errors.md +1103 -0
  66. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01_typescript_error_aggregation_patterns.md +789 -0
  67. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02-error-merge-strategy-testing-guide.md +1098 -0
  68. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02_aggregate_error_patterns.md +1037 -0
  69. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03-promise-allsettled-testing-patterns.md +916 -0
  70. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03_error_merging_strategies.md +1045 -0
  71. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/04_github_stackoverflow_examples.md +890 -0
  72. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/05_comprehensive_summary.md +822 -0
  73. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/INDEX.md +668 -0
  74. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/QUICK_REFERENCE.md +706 -0
  75. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/README.md +265 -0
  76. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/RESEARCH_REPORT.md +655 -0
  77. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S4/research/vitest_testing_patterns.md +1103 -0
  78. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T3S2/PRP.md +426 -0
  79. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/PRP.md +506 -0
  80. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/QUICK_REFERENCE.md +114 -0
  81. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/RESEARCH_SUMMARY.md +316 -0
  82. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/vitest_observer_error_logging_best_practices.md +754 -0
  83. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S3/PRP.md +612 -0
  84. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/PRP.md +719 -0
  85. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/README.md +215 -0
  86. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/analysis.md +765 -0
  87. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S3/PRP.md +718 -0
  88. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/DECISION.md +149 -0
  89. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/PRP.md +470 -0
  90. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/ULTRATHINK_PLAN.md +332 -0
  91. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/codebase_workflow_name_analysis.md +167 -0
  92. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/external_best_practices.md +265 -0
  93. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/validation_patterns.md +273 -0
  94. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S1/workflow_engine_ancestry_api_research.md +760 -0
  95. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S3-PRP.md +434 -0
  96. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S1/PRP.md +717 -0
  97. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/PRP.md +472 -0
  98. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/VALIDATION_REPORT.md +125 -0
  99. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/research/ULTRATHINK_PRP_PLAN.md +301 -0
  100. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/error-logging-best-practices.md +1170 -0
  101. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/research_typescript_partial_and_overloads.md +940 -0
  102. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-quick-reference.md +151 -0
  103. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-research.md +650 -0
  104. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/prd_snapshot.md +259 -0
  105. package/plan/001_d3bb02af4886/bugfix/P1M1T1S1/PRP.md +457 -0
  106. package/plan/001_d3bb02af4886/bugfix/RESEARCH_SUMMARY.md +346 -0
  107. package/plan/001_d3bb02af4886/bugfix/architecture/codebase_structure.md +311 -0
  108. package/plan/001_d3bb02af4886/bugfix/architecture/concurrent_execution_best_practices.md +1565 -0
  109. package/plan/001_d3bb02af4886/bugfix/architecture/error_handling_patterns.md +288 -0
  110. package/plan/001_d3bb02af4886/bugfix/architecture/promise_all_analysis.md +741 -0
  111. package/plan/001_d3bb02af4886/docs/PRP/P1M1T1S4-functional-workflow-error-state-capture-test.md +652 -0
  112. package/plan/001_d3bb02af4886/docs/PRP/PRP.md +527 -0
  113. package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S1-PRP.md +415 -0
  114. package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S2-PRP.md +378 -0
  115. package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S4-PRP.md +713 -0
  116. package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M2T1S4-PRP.md +370 -0
  117. package/plan/001_d3bb02af4886/docs/PRP_P1M3T1S3.md +499 -0
  118. package/plan/001_d3bb02af4886/docs/TEST_RESULTS.md +230 -0
  119. package/plan/001_d3bb02af4886/docs/bugfix/ANALYSIS_PRD_VS_IMPLEMENTATION.md +1134 -0
  120. package/plan/001_d3bb02af4886/docs/bugfix/GAP_ANALYSIS_SUMMARY.md +179 -0
  121. package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/PRP.md +629 -0
  122. package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/validation-report.md +214 -0
  123. package/plan/001_d3bb02af4886/docs/bugfix/PRP_P1M4T2S3.md +629 -0
  124. package/plan/001_d3bb02af4886/docs/bugfix/bugfix_PRP.md +529 -0
  125. package/plan/001_d3bb02af4886/docs/bugfix/bugfix_QUICK_REFERENCE.md +142 -0
  126. package/plan/001_d3bb02af4886/docs/bugfix/bugfix_README.md +304 -0
  127. package/plan/001_d3bb02af4886/docs/bugfix/bugfix_TEST_RESULTS.md +558 -0
  128. package/plan/001_d3bb02af4886/docs/bugfix/bugfix_VALIDATION_SUMMARY.md +256 -0
  129. package/plan/001_d3bb02af4886/docs/bugfix/system_context.md +346 -0
  130. package/plan/001_d3bb02af4886/docs/bugfix-architecture/bug_analysis.md +415 -0
  131. package/plan/001_d3bb02af4886/docs/bugfix-architecture/implementation_patterns.md +489 -0
  132. package/plan/001_d3bb02af4886/docs/bugfix-architecture/system_context.md +218 -0
  133. package/plan/001_d3bb02af4886/docs/bugfix_INITIATION_SUMMARY.md +380 -0
  134. package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_PATTERNS.md +1923 -0
  135. package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_QUICK_REF.md +319 -0
  136. package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/codebase-context.md +115 -0
  137. package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/cycle-detection-algorithms.md +134 -0
  138. package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/test-patterns.md +153 -0
  139. package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/workflow-class.md +132 -0
  140. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_BEST_PRACTICES.md +716 -0
  141. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_QUICK_REF.md +186 -0
  142. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/GROUNDSWELL_DECORATOR_EXAMPLES.md +604 -0
  143. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/INDEX.md +213 -0
  144. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/codebase_structure.md +30 -0
  145. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/existing_test_pattern.md +56 -0
  146. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/getRootObservers_implementation.md +53 -0
  147. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/test_conventions.md +49 -0
  148. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/PRP.md +958 -0
  149. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/QUICK_REFERENCE.md +339 -0
  150. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/README.md +305 -0
  151. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/SUMMARY.md +433 -0
  152. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/bidirectional-tree-consistency-testing.md +1574 -0
  153. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/test-pattern-examples.md +1014 -0
  154. package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_QUICK_REF.md +376 -0
  155. package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_RESEARCH.md +1507 -0
  156. package/plan/001_d3bb02af4886/docs/research/bugfix_typescript_patterns.md +949 -0
  157. package/plan/001_d3bb02af4886/docs/research/error-testing-research.md +619 -0
  158. package/plan/001_d3bb02af4886/docs/research/error_handling_patterns.md +723 -0
  159. package/plan/{research → 001_d3bb02af4886/docs/research/general}/introspection-security-guide.md +56 -0
  160. package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/PRP_TEMPLATE.md +460 -0
  161. package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/QUICK_REFERENCE.md +324 -0
  162. package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/README.md +175 -0
  163. package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/RESEARCH_REPORT.md +499 -0
  164. package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/SUMMARY.md +163 -0
  165. package/plan/bugfix/BUG_FIX_SUMMARY.md +961 -0
  166. package/src/__tests__/adversarial/attachChild-performance.test.ts +216 -0
  167. package/src/__tests__/adversarial/circular-reference.test.ts +101 -0
  168. package/src/__tests__/adversarial/complex-circular-reference.test.ts +139 -0
  169. package/src/__tests__/adversarial/concurrent-task-failures.test.ts +571 -0
  170. package/src/__tests__/adversarial/deep-analysis.test.ts +729 -0
  171. package/src/__tests__/adversarial/deep-hierarchy-stress.test.ts +213 -0
  172. package/src/__tests__/adversarial/e2e-prd-validation.test.ts +448 -0
  173. package/src/__tests__/adversarial/edge-case.test.ts +703 -0
  174. package/src/__tests__/adversarial/error-merge-strategy.test.ts +760 -0
  175. package/src/__tests__/adversarial/incremental-performance.test.ts +140 -0
  176. package/src/__tests__/adversarial/node-map-update-benchmarks.test.ts +457 -0
  177. package/src/__tests__/adversarial/observer-propagation.test.ts +487 -0
  178. package/src/__tests__/adversarial/parent-validation.test.ts +143 -0
  179. package/src/__tests__/adversarial/prd-12-2-compliance.test.ts +611 -0
  180. package/src/__tests__/adversarial/prd-compliance.test.ts +731 -0
  181. package/src/__tests__/compatibility/backward-compatibility.test.ts +1572 -0
  182. package/src/__tests__/helpers/index.ts +18 -0
  183. package/src/__tests__/helpers/tree-verification.ts +257 -0
  184. package/src/__tests__/integration/bidirectional-consistency.test.ts +847 -0
  185. package/src/__tests__/integration/observer-logging.test.ts +643 -0
  186. package/src/__tests__/integration/tree-mirroring.test.ts +37 -0
  187. package/src/__tests__/integration/workflow-reparenting.test.ts +303 -0
  188. package/src/__tests__/unit/context.test.ts +79 -0
  189. package/src/__tests__/unit/logger.test.ts +293 -0
  190. package/src/__tests__/unit/observable.test.ts +321 -0
  191. package/src/__tests__/unit/tree-debugger-incremental.test.ts +170 -0
  192. package/src/__tests__/unit/utils/workflow-error-utils.test.ts +209 -0
  193. package/src/__tests__/unit/workflow-detachChild.test.ts +100 -0
  194. package/src/__tests__/unit/workflow-emitEvent-childDetached.test.ts +153 -0
  195. package/src/__tests__/unit/workflow-isDescendantOf.test.ts +180 -0
  196. package/src/__tests__/unit/workflow.test.ts +277 -1
  197. package/src/core/agent.ts +21 -1
  198. package/src/core/logger.ts +27 -2
  199. package/src/core/workflow-context.ts +6 -4
  200. package/src/core/workflow.ts +252 -14
  201. package/src/debugger/tree-debugger.ts +52 -7
  202. package/src/decorators/task.ts +65 -2
  203. package/src/index.ts +4 -2
  204. package/src/types/decorators.ts +8 -1
  205. package/src/types/events.ts +1 -0
  206. package/src/utils/index.ts +1 -0
  207. package/src/utils/observable.ts +32 -3
  208. package/src/utils/workflow-error-utils.ts +56 -0
  209. package/tsconfig.json +1 -1
  210. package/llms_full.txt +0 -5890
  211. package/tasks.json +0 -0
  212. /package/plan/{backlog.json → 001_d3bb02af4886/backlog.json} +0 -0
  213. /package/plan/{P1P2/PRP.md → 001_d3bb02af4886/docs/PRP/P1P2-PRP.md} +0 -0
  214. /package/plan/{P3P4/PRP.md → 001_d3bb02af4886/docs/PRP/P3P4-PRP.md} +0 -0
  215. /package/plan/{P4P5/PRP.md → 001_d3bb02af4886/docs/PRP/P4P5-PRP.md} +0 -0
  216. /package/plan/{architecture → 001_d3bb02af4886/docs/architecture}/external_deps.md +0 -0
  217. /package/plan/{architecture → 001_d3bb02af4886/docs/architecture}/system_context.md +0 -0
  218. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/LRU_CACHE_BEST_PRACTICES.md +0 -0
  219. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/LRU_CACHE_CODE_PATTERNS.md +0 -0
  220. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/LRU_CACHE_INTEGRATION_GUIDE.md +0 -0
  221. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/LRU_CACHE_RESEARCH_INDEX.md +0 -0
  222. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/REFLECTION_INDEX.md +0 -0
  223. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/REFLECTION_RESEARCH_REPORT.md +0 -0
  224. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/RESEARCH_SUMMARY.md +0 -0
  225. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/anthropic-sdk.md +0 -0
  226. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/async-local-storage.md +0 -0
  227. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-code-patterns.md +0 -0
  228. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-decision-matrix.md +0 -0
  229. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-implementation-guide.md +0 -0
  230. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-integration-guide.md +0 -0
  231. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-patterns.md +0 -0
  232. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-quick-reference.md +0 -0
  233. /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/zod-schema.md +0 -0
  234. /package/plan/{P3P4/research → 001_d3bb02af4886/docs/research/P3P4}/caching-lru.md +0 -0
  235. /package/plan/{P3P4/research → 001_d3bb02af4886/docs/research/P3P4}/introspection-tools.md +0 -0
  236. /package/plan/{P3P4/research → 001_d3bb02af4886/docs/research/P3P4}/reflection-patterns.md +0 -0
  237. /package/plan/{P4P5/research → 001_d3bb02af4886/docs/research/P4P5}/RESEARCH_SUMMARY.md +0 -0
  238. /package/plan/{research → 001_d3bb02af4886/docs/research/general}/INTROSPECTION_RESEARCH_SUMMARY.md +0 -0
  239. /package/plan/{research → 001_d3bb02af4886/docs/research/general}/README-INTROSPECTION.md +0 -0
  240. /package/plan/{research → 001_d3bb02af4886/docs/research/general}/agent-introspection-patterns.md +0 -0
  241. /package/plan/{research → 001_d3bb02af4886/docs/research/general}/introspection-tool-examples.md +0 -0
  242. /package/{PRPs/PRDs/001-hierarchical-workflow-engine.md → plan/001_d3bb02af4886/prd_snapshot.md} +0 -0
@@ -0,0 +1,703 @@
1
+ /**
2
+ * Adversarial and Edge Case Tests for Hierarchical Workflow Engine
3
+ * These tests explore potential bugs, edge cases, and PRD compliance issues
4
+ */
5
+
6
+ import { describe, it, expect, beforeEach } from 'vitest';
7
+ import { Workflow, Step, Task, ObservedState } from '../../index.js';
8
+ import { WorkflowTreeDebugger } from '../../debugger/tree-debugger.js';
9
+
10
+ describe('Adversarial Edge Case Tests', () => {
11
+ describe('PRD Requirement: Step Decorator Defaults', () => {
12
+ /**
13
+ * PRD Section 8.1 specifies @Step options with defaults
14
+ * - trackTiming should be true by default (mentioned in skeleton but not explicit)
15
+ */
16
+
17
+ it('should track timing by default when trackTiming is not specified', async () => {
18
+ let stepEndEmitted = false;
19
+ let durationEmitted: number | undefined;
20
+
21
+ class TestWorkflow extends Workflow {
22
+ @Step()
23
+ async testStep() {
24
+ return 'done';
25
+ }
26
+
27
+ async run() {
28
+ return this.testStep();
29
+ }
30
+ }
31
+
32
+ const workflow = new TestWorkflow();
33
+ const debuggerInstance = new WorkflowTreeDebugger(workflow);
34
+
35
+ // Subscribe to events correctly
36
+ debuggerInstance.events.subscribe({
37
+ next: (event) => {
38
+ if (event.type === 'stepEnd') {
39
+ stepEndEmitted = true;
40
+ durationEmitted = event.duration;
41
+ }
42
+ },
43
+ });
44
+
45
+ await workflow.run();
46
+
47
+ expect(stepEndEmitted).toBe(true);
48
+ expect(typeof durationEmitted).toBe('number');
49
+ expect(durationEmitted!).toBeGreaterThanOrEqual(0);
50
+ });
51
+
52
+ it('should NOT track timing when explicitly set to false', async () => {
53
+ let stepEndEmitted = false;
54
+
55
+ class TestWorkflow extends Workflow {
56
+ @Step({ trackTiming: false })
57
+ async testStep() {
58
+ return 'done';
59
+ }
60
+
61
+ async run() {
62
+ return this.testStep();
63
+ }
64
+ }
65
+
66
+ const workflow = new TestWorkflow();
67
+ const debuggerInstance = new WorkflowTreeDebugger(workflow);
68
+
69
+ debuggerInstance.events.subscribe({
70
+ next: (event) => {
71
+ if (event.type === 'stepEnd') {
72
+ stepEndEmitted = true;
73
+ }
74
+ },
75
+ });
76
+
77
+ await workflow.run();
78
+
79
+ // stepEnd should NOT be emitted when trackTiming is false
80
+ // This is based on the implementation: trackTiming !== false controls emission
81
+ expect(stepEndEmitted).toBe(false);
82
+ });
83
+ });
84
+
85
+ describe('PRD Requirement: WorkflowLogger.child() Behavior', () => {
86
+ /**
87
+ * PRD Section 12.1 shows WorkflowLogger.child(meta: Partial<LogEntry>)
88
+ * But implementation shows: child(parentLogId: string)
89
+ * This is a mismatch between PRD and implementation
90
+ */
91
+
92
+ it('should have child() method that accepts parentLogId', async () => {
93
+ class TestWorkflow extends Workflow {
94
+ async run() {
95
+ // Access logger to verify child method exists
96
+ const childLogger = this.logger.child('parent-id-123');
97
+ expect(childLogger).toBeDefined();
98
+ }
99
+ }
100
+
101
+ const workflow = new TestWorkflow();
102
+ await workflow.run();
103
+ });
104
+ });
105
+
106
+ describe('Edge Case: Empty and Null Values', () => {
107
+ it('should reject empty string workflow name', async () => {
108
+ class TestWorkflow extends Workflow {
109
+ async run() {
110
+ return 'done';
111
+ }
112
+ }
113
+
114
+ expect(() => new TestWorkflow('')).toThrow('Workflow name cannot be empty or whitespace only');
115
+ });
116
+
117
+ it('should handle null and undefined observed state values', async () => {
118
+ class TestWorkflow extends Workflow {
119
+ @ObservedState()
120
+ nullableValue: string | null = null;
121
+
122
+ @ObservedState()
123
+ undefinedValue: string | undefined = undefined;
124
+
125
+ @ObservedState()
126
+ emptyValue = '';
127
+
128
+ async run() {
129
+ this.snapshotState();
130
+ return this.node.stateSnapshot;
131
+ }
132
+ }
133
+
134
+ const workflow = new TestWorkflow();
135
+ const snapshot = await workflow.run();
136
+
137
+ expect(snapshot).toHaveProperty('nullableValue', null);
138
+ expect(snapshot).toHaveProperty('undefinedValue', undefined);
139
+ expect(snapshot).toHaveProperty('emptyValue', '');
140
+ });
141
+
142
+ it('should handle empty array from @Task', async () => {
143
+ class ChildWorkflow extends Workflow {
144
+ async run() {
145
+ return 'child';
146
+ }
147
+ }
148
+
149
+ class ParentWorkflow extends Workflow {
150
+ @Task()
151
+ async returnsEmpty(): Promise<Workflow[]> {
152
+ return [];
153
+ }
154
+
155
+ async run() {
156
+ return this.returnsEmpty();
157
+ }
158
+ }
159
+
160
+ const workflow = new ParentWorkflow();
161
+ const result = await workflow.run();
162
+
163
+ expect(Array.isArray(result)).toBe(true);
164
+ expect(result.length).toBe(0);
165
+ });
166
+
167
+ it('should handle null return from @Task', async () => {
168
+ class ParentWorkflow extends Workflow {
169
+ @Task()
170
+ async returnsNull(): Promise<null> {
171
+ return null;
172
+ }
173
+
174
+ async run() {
175
+ return this.returnsNull();
176
+ }
177
+ }
178
+
179
+ const workflow = new ParentWorkflow();
180
+ const result = await workflow.run();
181
+
182
+ expect(result).toBe(null);
183
+ });
184
+
185
+ it('should handle undefined return from @Task', async () => {
186
+ class ParentWorkflow extends Workflow {
187
+ @Task()
188
+ async returnsUndefined(): Promise<undefined> {
189
+ return undefined;
190
+ }
191
+
192
+ async run() {
193
+ return this.returnsUndefined();
194
+ }
195
+ }
196
+
197
+ const workflow = new ParentWorkflow();
198
+ const result = await workflow.run();
199
+
200
+ expect(result).toBe(undefined);
201
+ });
202
+ });
203
+
204
+ describe('Edge Case: Unicode and Special Characters', () => {
205
+ it('should handle unicode in workflow names', async () => {
206
+ class TestWorkflow extends Workflow {
207
+ async run() {
208
+ return 'done';
209
+ }
210
+ }
211
+
212
+ const unicodeNames = [
213
+ '🚀 Rocket',
214
+ '测试工作流',
215
+ 'العملية',
216
+ '🎯Target',
217
+ ];
218
+
219
+ for (const name of unicodeNames) {
220
+ const workflow = new TestWorkflow(name);
221
+ expect(workflow.node.name).toBe(name);
222
+ await workflow.run();
223
+ }
224
+ });
225
+
226
+ it('should handle unicode in log messages', async () => {
227
+ class TestWorkflow extends Workflow {
228
+ async run() {
229
+ this.logger.info('测试消息 🚀');
230
+ this.logger.warn('⚠️ Warning');
231
+ this.logger.error('❌ Error with emoji');
232
+ }
233
+ }
234
+
235
+ const workflow = new TestWorkflow();
236
+ await workflow.run();
237
+
238
+ expect(workflow.node.logs.length).toBe(3);
239
+ expect(workflow.node.logs[0].message).toBe('测试消息 🚀');
240
+ });
241
+
242
+ it('should handle unicode in observed state values', async () => {
243
+ class TestWorkflow extends Workflow {
244
+ @ObservedState()
245
+ unicodeField = '测试 🎯';
246
+
247
+ async run() {
248
+ this.snapshotState();
249
+ return this.node.stateSnapshot;
250
+ }
251
+ }
252
+
253
+ const workflow = new TestWorkflow();
254
+ const snapshot = await workflow.run();
255
+
256
+ expect(snapshot?.unicodeField).toBe('测试 🎯');
257
+ });
258
+ });
259
+
260
+ describe('Edge Case: Deep Hierarchies', () => {
261
+ it('should handle very deep workflow hierarchies', async () => {
262
+ // Create a chain of 100 nested workflows
263
+ let lastWorkflow: any = null;
264
+
265
+ for (let i = 0; i < 100; i++) {
266
+ const name = `Workflow-${i}`;
267
+
268
+ const DynamicWorkflow = class extends Workflow {
269
+ @Step()
270
+ async doWork() {
271
+ return `level-${i}`;
272
+ }
273
+
274
+ async run() {
275
+ return this.doWork();
276
+ }
277
+ };
278
+
279
+ lastWorkflow = new DynamicWorkflow(name, lastWorkflow);
280
+ }
281
+
282
+ await lastWorkflow.run();
283
+
284
+ // Verify hierarchy depth
285
+ let depth = 0;
286
+ let current: any = lastWorkflow;
287
+ while (current.parent) {
288
+ depth++;
289
+ current = current.parent;
290
+ }
291
+
292
+ expect(depth).toBe(99);
293
+ });
294
+
295
+ it('should handle wide workflow hierarchies (many siblings)', async () => {
296
+ class ChildWorkflow extends Workflow {
297
+ @Step()
298
+ async doWork() {
299
+ return 'child-work';
300
+ }
301
+
302
+ async run() {
303
+ return this.doWork();
304
+ }
305
+ }
306
+
307
+ class ParentWorkflow extends Workflow {
308
+ @Task({ concurrent: true })
309
+ async spawnMany() {
310
+ return Array.from({ length: 50 }, (_, i) => new ChildWorkflow(`Child-${i}`, this));
311
+ }
312
+
313
+ async run() {
314
+ return this.spawnMany();
315
+ }
316
+ }
317
+
318
+ const workflow = new ParentWorkflow();
319
+ await workflow.run();
320
+
321
+ expect(workflow.children.length).toBe(50);
322
+ });
323
+ });
324
+
325
+ describe('Edge Case: Rapid State Changes', () => {
326
+ it('should handle rapid status changes', async () => {
327
+ class TestWorkflow extends Workflow {
328
+ async run() {
329
+ this.setStatus('running');
330
+ this.setStatus('running');
331
+ this.setStatus('running');
332
+ this.setStatus('completed');
333
+ }
334
+ }
335
+
336
+ const workflow = new TestWorkflow();
337
+ await workflow.run();
338
+
339
+ expect(workflow.status).toBe('completed');
340
+ expect(workflow.node.status).toBe('completed');
341
+ });
342
+
343
+ it('should handle multiple rapid snapshots', async () => {
344
+ class TestWorkflow extends Workflow {
345
+ @ObservedState()
346
+ counter = 0;
347
+
348
+ async run() {
349
+ for (let i = 0; i < 10; i++) {
350
+ this.counter = i;
351
+ this.snapshotState();
352
+ }
353
+ }
354
+ }
355
+
356
+ const workflow = new TestWorkflow();
357
+ await workflow.run();
358
+
359
+ expect(workflow.node.stateSnapshot?.counter).toBe(9);
360
+ });
361
+ });
362
+
363
+ describe('Edge Case: Concurrent Execution', () => {
364
+ it('should handle concurrent task execution with errors', async () => {
365
+ class GoodChild extends Workflow {
366
+ async run() {
367
+ return 'good';
368
+ }
369
+ }
370
+
371
+ class BadChild extends Workflow {
372
+ async run() {
373
+ throw new Error('Bad child error');
374
+ }
375
+ }
376
+
377
+ class ParentWorkflow extends Workflow {
378
+ @Task({ concurrent: true })
379
+ async spawnMixed() {
380
+ return [
381
+ new GoodChild('Good', this),
382
+ new BadChild('Bad', this),
383
+ ];
384
+ }
385
+
386
+ async run() {
387
+ // This should throw because concurrent runs happen
388
+ try {
389
+ await this.spawnMixed();
390
+ } catch (err) {
391
+ // Expected to throw
392
+ }
393
+ }
394
+ }
395
+
396
+ const workflow = new ParentWorkflow();
397
+ await workflow.run();
398
+
399
+ // Both children should be attached
400
+ expect(workflow.children.length).toBe(2);
401
+ });
402
+
403
+ it('should handle @Task with concurrent: true on single workflow', async () => {
404
+ class ChildWorkflow extends Workflow {
405
+ async run() {
406
+ return 'child-result';
407
+ }
408
+ }
409
+
410
+ class ParentWorkflow extends Workflow {
411
+ @Task({ concurrent: true })
412
+ async spawnOne() {
413
+ return new ChildWorkflow('SingleChild', this);
414
+ }
415
+
416
+ async run() {
417
+ return this.spawnOne();
418
+ }
419
+ }
420
+
421
+ const workflow = new ParentWorkflow();
422
+ const result = await workflow.run();
423
+
424
+ // Single workflow should still be returned
425
+ expect(result).toBeDefined();
426
+ expect(workflow.children.length).toBe(1);
427
+ });
428
+ });
429
+
430
+ describe('Edge Case: Observers and Event Handling', () => {
431
+ it('should handle observer that throws errors', async () => {
432
+ class TestWorkflow extends Workflow {
433
+ async run() {
434
+ this.emitEvent({ type: 'stepStart', node: this.node, step: 'test' });
435
+ }
436
+ }
437
+
438
+ const workflow = new TestWorkflow();
439
+
440
+ // Add an observer that throws
441
+ workflow.addObserver({
442
+ onLog: () => {
443
+ throw new Error('Observer error');
444
+ },
445
+ onEvent: () => {
446
+ throw new Error('Event observer error');
447
+ },
448
+ onStateUpdated: () => {
449
+ throw new Error('State observer error');
450
+ },
451
+ onTreeChanged: () => {
452
+ throw new Error('Tree observer error');
453
+ },
454
+ });
455
+
456
+ // Should not throw, errors are caught and console.error'd
457
+ await workflow.run();
458
+ });
459
+
460
+ it('should handle multiple observers', async () => {
461
+ class TestWorkflow extends Workflow {
462
+ async run() {
463
+ this.emitEvent({ type: 'stepStart', node: this.node, step: 'test' });
464
+ }
465
+ }
466
+
467
+ const workflow = new TestWorkflow();
468
+
469
+ const counts = { onLog: 0, onEvent: 0, onStateUpdated: 0, onTreeChanged: 0 };
470
+
471
+ // Add multiple observers
472
+ for (let i = 0; i < 5; i++) {
473
+ workflow.addObserver({
474
+ onLog: () => counts.onLog++,
475
+ onEvent: () => counts.onEvent++,
476
+ onStateUpdated: () => counts.onStateUpdated++,
477
+ onTreeChanged: () => counts.onTreeChanged++,
478
+ });
479
+ }
480
+
481
+ await workflow.run();
482
+
483
+ // Each observer should have been called
484
+ expect(counts.onEvent).toBe(5);
485
+ });
486
+ });
487
+
488
+ describe('Edge Case: Circular References', () => {
489
+ it('should detect circular parent-child relationships', async () => {
490
+ class TestWorkflow extends Workflow {
491
+ async run() {
492
+ return 'done';
493
+ }
494
+ }
495
+
496
+ const parent = new TestWorkflow('Parent');
497
+ const child = new TestWorkflow('Child', parent);
498
+
499
+ // Try to create a circular reference
500
+ expect(() => {
501
+ parent.attachChild(child as any); // This should throw
502
+ }).toThrow('Child already attached');
503
+ });
504
+
505
+ it('should prevent creating cycles through getRoot', async () => {
506
+ class TestWorkflow extends Workflow {
507
+ async run() {
508
+ return 'done';
509
+ }
510
+ }
511
+
512
+ const root = new TestWorkflow('Root');
513
+ const child = new TestWorkflow('Child', root);
514
+
515
+ // getRoot should work correctly
516
+ const rootFromChild = (child as any).getRoot();
517
+ expect(rootFromChild.id).toBe(root.id);
518
+ });
519
+ });
520
+
521
+ describe('Edge Case: Memory and Performance', () => {
522
+ it('should handle large number of events', async () => {
523
+ class TestWorkflow extends Workflow {
524
+ async run() {
525
+ for (let i = 0; i < 1000; i++) {
526
+ this.emitEvent({ type: 'stepStart', node: this.node, step: `step-${i}` });
527
+ }
528
+ }
529
+ }
530
+
531
+ const workflow = new TestWorkflow();
532
+ await workflow.run();
533
+
534
+ expect(workflow.node.events.length).toBe(1000);
535
+ });
536
+
537
+ it('should handle large number of logs', async () => {
538
+ class TestWorkflow extends Workflow {
539
+ async run() {
540
+ for (let i = 0; i < 1000; i++) {
541
+ this.logger.info(`Log entry ${i}`);
542
+ }
543
+ }
544
+ }
545
+
546
+ const workflow = new TestWorkflow();
547
+ await workflow.run();
548
+
549
+ expect(workflow.node.logs.length).toBe(1000);
550
+ });
551
+ });
552
+
553
+ describe('PRD Compliance: Error Event Format', () => {
554
+ /**
555
+ * PRD Section 5.1 specifies WorkflowError interface
556
+ * Verifying the error structure matches PRD
557
+ */
558
+
559
+ it('should emit error with all required fields', async () => {
560
+ class TestWorkflow extends Workflow {
561
+ @ObservedState()
562
+ testField = 'test-value';
563
+
564
+ @Step()
565
+ async failingStep() {
566
+ this.logger.info('About to fail');
567
+ throw new Error('Test error');
568
+ }
569
+
570
+ async run() {
571
+ try {
572
+ await this.failingStep();
573
+ } catch (err) {
574
+ // Expected
575
+ }
576
+ }
577
+ }
578
+
579
+ const workflow = new TestWorkflow();
580
+ let capturedError: any = null;
581
+
582
+ workflow.addObserver({
583
+ onLog: () => {},
584
+ onEvent: (event) => {
585
+ if (event.type === 'error') {
586
+ capturedError = event.error;
587
+ }
588
+ },
589
+ onStateUpdated: () => {},
590
+ onTreeChanged: () => {},
591
+ });
592
+
593
+ await workflow.run();
594
+
595
+ expect(capturedError).not.toBeNull();
596
+ expect(capturedError.message).toBe('Test error');
597
+ expect(capturedError.workflowId).toBe(workflow.id);
598
+ expect(capturedError.original).toBeDefined();
599
+ expect(capturedError.state).toBeDefined();
600
+ expect(capturedError.logs).toBeDefined();
601
+ expect(Array.isArray(capturedError.logs)).toBe(true);
602
+ });
603
+ });
604
+
605
+ describe('PRD Compliance: Event Types', () => {
606
+ /**
607
+ * PRD Section 4.2 specifies all WorkflowEvent types
608
+ * Verifying all event types are properly emitted
609
+ */
610
+
611
+ it('should emit childAttached event', async () => {
612
+ class ChildWorkflow extends Workflow {
613
+ async run() {
614
+ return 'child';
615
+ }
616
+ }
617
+
618
+ class ParentWorkflow extends Workflow {
619
+ @Task()
620
+ async spawnChild() {
621
+ return new ChildWorkflow('Child', this);
622
+ }
623
+
624
+ async run() {
625
+ return this.spawnChild();
626
+ }
627
+ }
628
+
629
+ const workflow = new ParentWorkflow();
630
+ let childAttachedFired = false;
631
+
632
+ workflow.addObserver({
633
+ onLog: () => {},
634
+ onEvent: (event) => {
635
+ if (event.type === 'childAttached') {
636
+ childAttachedFired = true;
637
+ expect(event.parentId).toBe(workflow.id);
638
+ expect(event.child).toBeDefined();
639
+ }
640
+ },
641
+ onStateUpdated: () => {},
642
+ onTreeChanged: () => {},
643
+ });
644
+
645
+ await workflow.run();
646
+ expect(childAttachedFired).toBe(true);
647
+ });
648
+
649
+ it('should emit stateSnapshot event', async () => {
650
+ class TestWorkflow extends Workflow {
651
+ @ObservedState()
652
+ testField = 'value';
653
+
654
+ async run() {
655
+ this.snapshotState();
656
+ }
657
+ }
658
+
659
+ const workflow = new TestWorkflow();
660
+ let snapshotFired = false;
661
+
662
+ workflow.addObserver({
663
+ onLog: () => {},
664
+ onEvent: (event) => {
665
+ if (event.type === 'stateSnapshot') {
666
+ snapshotFired = true;
667
+ expect(event.node).toBeDefined();
668
+ }
669
+ },
670
+ onStateUpdated: () => {},
671
+ onTreeChanged: () => {},
672
+ });
673
+
674
+ await workflow.run();
675
+ expect(snapshotFired).toBe(true);
676
+ });
677
+
678
+ it('should emit treeUpdated event', async () => {
679
+ class TestWorkflow extends Workflow {
680
+ async run() {
681
+ this.emitEvent({ type: 'treeUpdated', root: this.node });
682
+ }
683
+ }
684
+
685
+ const workflow = new TestWorkflow();
686
+ let treeUpdatedFired = false;
687
+
688
+ workflow.addObserver({
689
+ onLog: () => {},
690
+ onEvent: (event) => {
691
+ if (event.type === 'treeUpdated') {
692
+ treeUpdatedFired = true;
693
+ }
694
+ },
695
+ onStateUpdated: () => {},
696
+ onTreeChanged: () => {},
697
+ });
698
+
699
+ await workflow.run();
700
+ expect(treeUpdatedFired).toBe(true);
701
+ });
702
+ });
703
+ });