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
@@ -3,6 +3,7 @@ import type {
3
3
  WorkflowStatus,
4
4
  WorkflowEvent,
5
5
  WorkflowObserver,
6
+ LogEntry,
6
7
  } from '../types/index.js';
7
8
  import type { WorkflowContext, WorkflowConfig, WorkflowResult } from '../types/workflow-context.js';
8
9
  import { generateId } from '../utils/id.js';
@@ -57,7 +58,7 @@ export class Workflow<T = unknown> {
57
58
  protected readonly logger: WorkflowLogger;
58
59
 
59
60
  /** The node representation of this workflow */
60
- protected readonly node: WorkflowNode;
61
+ public readonly node: WorkflowNode;
61
62
 
62
63
  /** Observers (only populated on root workflow) */
63
64
  private observers: WorkflowObserver[] = [];
@@ -94,6 +95,17 @@ export class Workflow<T = unknown> {
94
95
  this.parent = (parentOrExecutor as Workflow) ?? null;
95
96
  }
96
97
 
98
+ // Validate workflow name (after config is normalized)
99
+ if (typeof this.config.name === 'string') {
100
+ const trimmedName = this.config.name.trim();
101
+ if (trimmedName.length === 0) {
102
+ throw new Error('Workflow name cannot be empty or whitespace only');
103
+ }
104
+ if (this.config.name.length > 100) {
105
+ throw new Error('Workflow name cannot exceed 100 characters');
106
+ }
107
+ }
108
+
97
109
  // Create the node representation
98
110
  this.node = {
99
111
  id: this.id,
@@ -118,22 +130,113 @@ export class Workflow<T = unknown> {
118
130
  /**
119
131
  * Get observers from the root workflow
120
132
  * Traverses up the tree to find the root
133
+ * Uses cycle detection to prevent infinite loops from circular parent-child relationships
121
134
  */
122
135
  private getRootObservers(): WorkflowObserver[] {
123
- if (this.parent) {
124
- return this.parent.getRootObservers();
136
+ const visited = new Set<Workflow>();
137
+ let root: Workflow = this;
138
+ let current: Workflow | null = this;
139
+
140
+ while (current) {
141
+ if (visited.has(current)) {
142
+ throw new Error('Circular parent-child relationship detected');
143
+ }
144
+ visited.add(current);
145
+ root = current;
146
+ current = current.parent;
147
+ }
148
+
149
+ return root.observers;
150
+ }
151
+
152
+ /**
153
+ * Check if this workflow is a descendant of the given ancestor workflow.
154
+ *
155
+ * Traverses the parent chain upward looking for the ancestor reference.
156
+ * Uses a visited Set to detect cycles during traversal. This method provides
157
+ * a convenient way to check workflow hierarchy relationships without manually
158
+ * traversing the parent chain.
159
+ *
160
+ * @warning This method reveals workflow hierarchy information. If your
161
+ * application exposes workflows via an API, ensure you implement proper
162
+ * access control to prevent unauthorized topology discovery. Note that
163
+ * the `parent` and `children` properties are already public, so this
164
+ * method does not expose any new information beyond what is currently
165
+ * accessible.
166
+ *
167
+ * **Time Complexity**: O(d) where d is the depth of the hierarchy
168
+ * **Space Complexity**: O(d) for the visited Set in worst case (cycle detection)
169
+ *
170
+ * @example Check if a workflow belongs to a specific hierarchy
171
+ * ```typescript
172
+ * const root = new Workflow('root');
173
+ * const child = new Workflow('child', { parent: root });
174
+ *
175
+ * if (child.isDescendantOf(root)) {
176
+ * console.log('Child is in root hierarchy');
177
+ * }
178
+ * ```
179
+ *
180
+ * @example Validate before attaching to prevent circular references
181
+ * ```typescript
182
+ * if (!newChild.isDescendantOf(parent)) {
183
+ * parent.attachChild(newChild);
184
+ * } else {
185
+ * throw new Error('Would create circular reference');
186
+ * }
187
+ * ```
188
+ *
189
+ * @example Check for ancestor relationship in conditional logic
190
+ * ```typescript
191
+ * const isInProductionBranch = workflow.isDescendantOf(productionRoot);
192
+ * if (isInProductionBranch) {
193
+ * // Apply production-specific logic
194
+ * }
195
+ * ```
196
+ *
197
+ * @param ancestor - The potential ancestor workflow to check
198
+ * @returns true if ancestor is found in parent chain, false otherwise
199
+ * @throws {Error} If a cycle is detected during traversal (indicates corrupted tree structure)
200
+ */
201
+ public isDescendantOf(ancestor: Workflow): boolean {
202
+ const visited = new Set<Workflow>();
203
+ let current: Workflow | null = this.parent;
204
+
205
+ while (current !== null) {
206
+ if (visited.has(current)) {
207
+ throw new Error('Circular parent-child relationship detected');
208
+ }
209
+ visited.add(current);
210
+
211
+ if (current === ancestor) {
212
+ return true;
213
+ }
214
+
215
+ current = current.parent;
125
216
  }
126
- return this.observers;
217
+
218
+ return false;
127
219
  }
128
220
 
129
221
  /**
130
222
  * Get the root workflow
223
+ * Uses cycle detection to prevent infinite loops from circular parent-child relationships
131
224
  */
132
225
  protected getRoot(): Workflow {
133
- if (this.parent) {
134
- return this.parent.getRoot();
226
+ const visited = new Set<Workflow>();
227
+ let root: Workflow = this;
228
+ let current: Workflow | null = this;
229
+
230
+ while (current) {
231
+ if (visited.has(current)) {
232
+ throw new Error('Circular parent-child relationship detected');
233
+ }
234
+ visited.add(current);
235
+ root = current;
236
+ current = current.parent;
135
237
  }
136
- return this;
238
+
239
+ return root;
137
240
  }
138
241
 
139
242
  /**
@@ -158,10 +261,88 @@ export class Workflow<T = unknown> {
158
261
  }
159
262
 
160
263
  /**
161
- * Attach a child workflow
162
- * Called automatically in constructor when parent is provided
264
+ * Attach a child workflow to this parent workflow.
265
+ *
266
+ * Validates that the child can be attached by checking:
267
+ * 1. Child is not already attached to this parent workflow
268
+ * 2. Child does not have a different parent (enforces single-parent invariant)
269
+ * 3. Child is not an ancestor of this parent (prevents circular references)
270
+ *
271
+ * **Structural Changes:**
272
+ * - Adds child to this.children array (workflow tree)
273
+ * - Adds child.node to this.node.children array (node tree)
274
+ * - Sets child.parent = this (workflow tree)
275
+ * - Sets child.node.parent = this.node (node tree)
276
+ * - Emits childAttached event to notify observers
277
+ *
278
+ * **Invariants Maintained:**
279
+ * - Single-parent rule: A workflow can only have one parent
280
+ * - 1:1 tree mirror: workflow tree and node tree stay synchronized
281
+ * - No cycles: A workflow cannot be its own ancestor
282
+ *
283
+ * **Cycle Detection:**
284
+ * - Uses isDescendantOf() helper with Set-based cycle detection
285
+ * - Throws immediately if circular reference would be created
286
+ *
287
+ * @param child - The child workflow to attach
288
+ * @throws {Error} If the child is already attached to this workflow
289
+ * @throws {Error} If the child already has a different parent (use detachChild() first for reparenting)
290
+ * @throws {Error} If the child is an ancestor of this parent (would create circular reference)
291
+ *
292
+ * @example
293
+ * ```ts
294
+ * const parent = new Workflow('Parent');
295
+ * const child = new Workflow('Child');
296
+ * parent.attachChild(child);
297
+ * // child.parent === parent
298
+ * // parent.children.includes(child) === true
299
+ * ```
300
+ *
301
+ * @example Reparenting workflow
302
+ * ```ts
303
+ * const parent1 = new Workflow('Parent1');
304
+ * const parent2 = new Workflow('Parent2');
305
+ * const child = new Workflow('Child', parent1); // Attached to parent1
306
+ *
307
+ * // Later, move child to parent2
308
+ * parent1.detachChild(child);
309
+ * parent2.attachChild(child);
310
+ * // child.parent === parent2
311
+ * ```
312
+ *
313
+ * @see detachChild - For detaching children (enables reparenting)
314
+ * @see isDescendantOf - Private helper for circular reference detection
163
315
  */
164
316
  public attachChild(child: Workflow): void {
317
+ if (this.children.includes(child)) {
318
+ throw new Error('Child already attached to this workflow');
319
+ }
320
+
321
+ // Check if child already has a different parent
322
+ if (child.parent !== null && child.parent !== this) {
323
+ const errorMessage =
324
+ `Child '${child.node.name}' already has a parent '${child.parent.node.name}'. ` +
325
+ `A workflow can only have one parent. ` +
326
+ `Use detachChild() on '${child.parent.node.name}' first if you need to reparent.`;
327
+ console.error(errorMessage);
328
+ throw new Error(errorMessage);
329
+ }
330
+
331
+ // Check if child is an ancestor (would create circular reference)
332
+ if (this.isDescendantOf(child)) {
333
+ const errorMessage =
334
+ `Cannot attach child '${child.node.name}' - it is an ancestor of '${this.node.name}'. ` +
335
+ `This would create a circular reference.`;
336
+ console.error(errorMessage);
337
+ throw new Error(errorMessage);
338
+ }
339
+
340
+ // Update child's parent if it's currently null
341
+ if (child.parent === null) {
342
+ child.parent = this;
343
+ child.node.parent = this.node; // Maintain 1:1 mirror between workflow tree and node tree
344
+ }
345
+
165
346
  this.children.push(child);
166
347
  this.node.children.push(child.node);
167
348
 
@@ -173,6 +354,59 @@ export class Workflow<T = unknown> {
173
354
  });
174
355
  }
175
356
 
357
+ /**
358
+ * Detach a child workflow from this parent workflow.
359
+ *
360
+ * Removes the child from both the workflow tree (this.children) and
361
+ * the node tree (this.node.children), clears the child's parent reference,
362
+ * and emits a childDetached event to notify observers.
363
+ *
364
+ * This enables reparenting workflows: oldParent.detachChild(child); newParent.attachChild(child);
365
+ *
366
+ * @param child - The child workflow to detach
367
+ * @throws {Error} If the child is not attached to this parent workflow
368
+ *
369
+ * @example
370
+ * ```ts
371
+ * const parent = new Workflow('Parent');
372
+ * const child = new Workflow('Child', parent);
373
+ *
374
+ * // Later, reparent to a different parent
375
+ * parent.detachChild(child);
376
+ * newParent.attachChild(child);
377
+ * ```
378
+ */
379
+ public detachChild(child: Workflow): void {
380
+ // Validate child is actually attached
381
+ const index = this.children.indexOf(child);
382
+
383
+ if (index === -1) {
384
+ throw new Error(
385
+ `Child '${child.node.name}' is not attached to workflow '${this.node.name}'`
386
+ );
387
+ }
388
+
389
+ // Remove from workflow tree (this.children array)
390
+ this.children.splice(index, 1);
391
+
392
+ // Remove from node tree (this.node.children array)
393
+ const nodeIndex = this.node.children.indexOf(child.node);
394
+ if (nodeIndex !== -1) {
395
+ this.node.children.splice(nodeIndex, 1);
396
+ }
397
+
398
+ // Clear child's parent reference (both workflow tree and node tree)
399
+ child.parent = null;
400
+ child.node.parent = null; // Maintain 1:1 mirror between workflow tree and node tree
401
+
402
+ // Emit childDetached event
403
+ this.emitEvent({
404
+ type: 'childDetached',
405
+ parentId: this.id,
406
+ childId: child.id,
407
+ });
408
+ }
409
+
176
410
  /**
177
411
  * Emit an event to all root observers
178
412
  */
@@ -185,11 +419,11 @@ export class Workflow<T = unknown> {
185
419
  obs.onEvent(event);
186
420
 
187
421
  // Also notify tree changed for tree update events
188
- if (event.type === 'treeUpdated' || event.type === 'childAttached') {
422
+ if (event.type === 'treeUpdated' || event.type === 'childAttached' || event.type === 'childDetached') {
189
423
  obs.onTreeChanged(this.getRoot().node);
190
424
  }
191
425
  } catch (err) {
192
- console.error('Observer onEvent error:', err);
426
+ this.logger.error('Observer onEvent error', { error: err, eventType: event.type });
193
427
  }
194
428
  }
195
429
  }
@@ -207,7 +441,7 @@ export class Workflow<T = unknown> {
207
441
  try {
208
442
  obs.onStateUpdated(this.node);
209
443
  } catch (err) {
210
- console.error('Observer onStateUpdated error:', err);
444
+ this.logger.error('Observer onStateUpdated error', { error: err, nodeId: this.node.id });
211
445
  }
212
446
  }
213
447
 
@@ -216,6 +450,9 @@ export class Workflow<T = unknown> {
216
450
  type: 'stateSnapshot',
217
451
  node: this.node,
218
452
  });
453
+
454
+ // Emit treeUpdated event to trigger tree debugger rebuild
455
+ this.emitEvent({ type: 'treeUpdated', root: this.getRoot().node });
219
456
  }
220
457
 
221
458
  /**
@@ -224,6 +461,7 @@ export class Workflow<T = unknown> {
224
461
  public setStatus(status: WorkflowStatus): void {
225
462
  this.status = status;
226
463
  this.node.status = status;
464
+ this.emitEvent({ type: 'treeUpdated', root: this.getRoot().node });
227
465
  }
228
466
 
229
467
  /**
@@ -291,8 +529,8 @@ export class Workflow<T = unknown> {
291
529
  original: error,
292
530
  workflowId: this.id,
293
531
  stack: error instanceof Error ? error.stack : undefined,
294
- state: {},
295
- logs: [],
532
+ state: getObservedState(this),
533
+ logs: [...this.node.logs] as LogEntry[],
296
534
  },
297
535
  });
298
536
 
@@ -57,6 +57,32 @@ export class WorkflowTreeDebugger implements WorkflowObserver {
57
57
  }
58
58
  }
59
59
 
60
+ /**
61
+ * Remove entire subtree from node map using BFS traversal
62
+ * O(k) complexity where k = number of nodes in subtree
63
+ * Uses iterative BFS to avoid stack overflow on deep trees
64
+ */
65
+ private removeSubtreeNodes(nodeId: string): void {
66
+ const node = this.nodeMap.get(nodeId);
67
+ if (!node) return; // Already removed or never existed
68
+
69
+ // BFS traversal to collect all descendant IDs
70
+ const toRemove: string[] = [];
71
+ const queue: WorkflowNode[] = [node];
72
+
73
+ while (queue.length > 0) {
74
+ const current = queue.shift()!;
75
+ toRemove.push(current.id);
76
+ // Add children to queue for BFS traversal
77
+ queue.push(...current.children);
78
+ }
79
+
80
+ // Batch delete all collected keys (atomic update)
81
+ for (const id of toRemove) {
82
+ this.nodeMap.delete(id);
83
+ }
84
+ }
85
+
60
86
  // WorkflowObserver implementation
61
87
 
62
88
  onLog(_entry: LogEntry): void {
@@ -64,12 +90,29 @@ export class WorkflowTreeDebugger implements WorkflowObserver {
64
90
  }
65
91
 
66
92
  onEvent(event: WorkflowEvent): void {
67
- // Rebuild node map on structural changes
68
- if (event.type === 'childAttached') {
69
- this.buildNodeMap(event.child);
93
+ // Handle structural events with incremental updates
94
+ switch (event.type) {
95
+ case 'childAttached':
96
+ // Keep existing logic - already optimal O(k)
97
+ this.buildNodeMap(event.child);
98
+ break;
99
+
100
+ case 'childDetached':
101
+ // NEW: Incremental subtree removal
102
+ this.removeSubtreeNodes(event.childId);
103
+ break;
104
+
105
+ case 'treeUpdated':
106
+ // NEW: Update root reference only
107
+ this.root = event.root;
108
+ break;
109
+
110
+ default:
111
+ // Non-structural events - no map update needed
112
+ break;
70
113
  }
71
114
 
72
- // Forward to event stream
115
+ // Always forward to event stream (existing behavior)
73
116
  this.events.next(event);
74
117
  }
75
118
 
@@ -78,9 +121,11 @@ export class WorkflowTreeDebugger implements WorkflowObserver {
78
121
  }
79
122
 
80
123
  onTreeChanged(root: WorkflowNode): void {
81
- this.root = root;
82
- this.nodeMap.clear();
83
- this.buildNodeMap(root);
124
+ // All tree changes now handled incrementally in onEvent()
125
+ // Just update root reference if different
126
+ if (this.root !== root) {
127
+ this.root = root;
128
+ }
84
129
  }
85
130
 
86
131
  // Public API
@@ -1,4 +1,5 @@
1
- import type { TaskOptions, WorkflowNode, WorkflowEvent } from '../types/index.js';
1
+ import type { TaskOptions, WorkflowNode, WorkflowEvent, WorkflowError, SerializedWorkflowState } from '../types/index.js';
2
+ import { mergeWorkflowErrors } from '../utils/workflow-error-utils.js';
2
3
 
3
4
  // Type for workflow-like objects
4
5
  interface WorkflowLike {
@@ -29,6 +30,38 @@ interface WorkflowClass {
29
30
  * ];
30
31
  * }
31
32
  * }
33
+ *
34
+ * @example Non-workflow return (silently skipped)
35
+ * class MyWorkflow extends Workflow {
36
+ * @Task()
37
+ * async returnsString(): Promise<string> {
38
+ * return 'not a workflow'; // Returned as-is, not attached
39
+ * }
40
+ * }
41
+ *
42
+ * @example Mixed return (only workflows attached)
43
+ * class MyWorkflow extends Workflow {
44
+ * @Task()
45
+ * async mixedReturn(): Promise<(Workflow | string)[]> {
46
+ * return [
47
+ * new ChildWorkflow('child1', this), // Attached
48
+ * 'some string', // Skipped
49
+ * new ChildWorkflow('child2', this), // Attached
50
+ * ];
51
+ * }
52
+ * }
53
+ *
54
+ * Validation Behavior
55
+ *
56
+ * The decorator uses lenient validation for return values:
57
+ * - Workflow objects (with 'id' property) are automatically attached
58
+ * - Non-workflow objects are silently skipped (not attached)
59
+ * - The original return value is always preserved
60
+ *
61
+ * This lenient approach enables:
62
+ * - Duck-typing: Works with workflow-like objects, not just Workflow instances
63
+ * - Flexible signatures: Methods can return any type without breaking
64
+ * - Graceful handling: Edge cases (null, undefined, primitives) don't throw errors
32
65
  */
33
66
  export function Task(opts: TaskOptions = {}) {
34
67
  return function <This, Args extends unknown[], Return>(
@@ -77,7 +110,37 @@ export function Task(opts: TaskOptions = {}) {
77
110
  );
78
111
 
79
112
  if (runnable.length > 0) {
80
- await Promise.all(runnable.map((w) => w.run()));
113
+ const results = await Promise.allSettled(runnable.map((w) => w.run()));
114
+
115
+ const rejected = results.filter(
116
+ (r): r is PromiseRejectedResult => r.status === 'rejected'
117
+ );
118
+
119
+ if (rejected.length > 0) {
120
+ // Check if error merge strategy is enabled
121
+ if (opts.errorMergeStrategy?.enabled) {
122
+ // Extract WorkflowError objects from rejected promises
123
+ const errors = rejected.map((r) => r.reason as WorkflowError);
124
+
125
+ // Merge errors using custom combine() or default merger
126
+ const mergedError = opts.errorMergeStrategy?.combine
127
+ ? opts.errorMergeStrategy.combine(errors)
128
+ : mergeWorkflowErrors(errors, taskName, wf.id, runnable.length);
129
+
130
+ // Emit error event with merged error
131
+ wf.emitEvent({
132
+ type: 'error',
133
+ node: wf.node,
134
+ error: mergedError,
135
+ });
136
+
137
+ // Throw merged error
138
+ throw mergedError;
139
+ }
140
+
141
+ // Backward compatibility: throw first error
142
+ throw rejected[0].reason;
143
+ }
81
144
  }
82
145
  }
83
146
 
package/src/index.ts CHANGED
@@ -84,6 +84,7 @@ export { WorkflowTreeDebugger } from './debugger/tree-debugger.js';
84
84
  export { Observable } from './utils/observable.js';
85
85
  export type { Subscription, Observer } from './utils/observable.js';
86
86
  export { generateId } from './utils/id.js';
87
+ export { mergeWorkflowErrors } from './utils/workflow-error-utils.js';
87
88
 
88
89
  // Factory functions
89
90
  export {
@@ -136,5 +137,6 @@ export type {
136
137
  } from './tools/introspection.js';
137
138
 
138
139
  // Examples (for reference)
139
- export { TestCycleWorkflow } from './examples/test-cycle-workflow.js';
140
- export { TDDOrchestrator } from './examples/tdd-orchestrator.js';
140
+ // Temporarily commented out due to decorator compatibility issues with vitest
141
+ // export { TestCycleWorkflow } from './examples/test-cycle-workflow.js';
142
+ // export { TDDOrchestrator } from './examples/tdd-orchestrator.js';
@@ -1,3 +1,5 @@
1
+ import type { ErrorMergeStrategy } from './error-strategy.js';
2
+
1
3
  /**
2
4
  * Configuration options for @Step decorator
3
5
  */
@@ -6,7 +8,7 @@ export interface StepOptions {
6
8
  name?: string;
7
9
  /** If true, capture state snapshot after step completion */
8
10
  snapshotState?: boolean;
9
- /** If true, track and emit step duration */
11
+ /** Track and emit step duration (default: true) */
10
12
  trackTiming?: boolean;
11
13
  /** If true, log message at step start */
12
14
  logStart?: boolean;
@@ -16,10 +18,15 @@ export interface StepOptions {
16
18
 
17
19
  /**
18
20
  * Configuration options for @Task decorator
21
+ *
22
+ * @note The decorator uses lenient validation - non-Workflow returns are
23
+ * silently skipped. See the @Task decorator JSDoc for details.
19
24
  */
20
25
  export interface TaskOptions {
21
26
  /** Custom task name (defaults to method name) */
22
27
  name?: string;
23
28
  /** If true, run returned workflows concurrently */
24
29
  concurrent?: boolean;
30
+ /** Strategy for merging errors from concurrent task execution */
31
+ errorMergeStrategy?: ErrorMergeStrategy;
25
32
  }
@@ -8,6 +8,7 @@ import type { TokenUsage } from './sdk-primitives.js';
8
8
  export type WorkflowEvent =
9
9
  // Core workflow events
10
10
  | { type: 'childAttached'; parentId: string; child: WorkflowNode }
11
+ | { type: 'childDetached'; parentId: string; childId: string }
11
12
  | { type: 'stateSnapshot'; node: WorkflowNode }
12
13
  | { type: 'stepStart'; node: WorkflowNode; step: string }
13
14
  | { type: 'stepEnd'; node: WorkflowNode; step: string; duration: number }
@@ -1,3 +1,4 @@
1
1
  export { generateId } from './id.js';
2
2
  export { Observable } from './observable.js';
3
+ export { mergeWorkflowErrors } from './workflow-error-utils.js';
3
4
  export type { Subscription, Observer } from './observable.js';
@@ -12,8 +12,25 @@ export interface Observer<T> {
12
12
  complete?: () => void;
13
13
  }
14
14
 
15
+ /**
16
+ * Logger interface for Observable error logging
17
+ * Matches WorkflowLogger.error() signature for compatibility
18
+ */
19
+ export interface ObservableLogger {
20
+ error(message: string, data?: unknown): void;
21
+ }
22
+
15
23
  export class Observable<T> {
16
24
  private subscribers: Set<Observer<T>> = new Set();
25
+ private logger?: ObservableLogger;
26
+
27
+ /**
28
+ * Create a new Observable
29
+ * @param logger Optional logger for error reporting (falls back to console.error)
30
+ */
31
+ constructor(logger?: ObservableLogger) {
32
+ this.logger = logger;
33
+ }
17
34
 
18
35
  /**
19
36
  * Subscribe to this observable
@@ -28,6 +45,18 @@ export class Observable<T> {
28
45
  };
29
46
  }
30
47
 
48
+ /**
49
+ * Log errors using injected logger or fallback to console.error
50
+ */
51
+ private logError(message: string, error: unknown): void {
52
+ if (this.logger) {
53
+ this.logger.error(message, { error });
54
+ } else {
55
+ // Fallback for backward compatibility
56
+ console.error(message, error);
57
+ }
58
+ }
59
+
31
60
  /**
32
61
  * Emit a value to all subscribers
33
62
  */
@@ -36,7 +65,7 @@ export class Observable<T> {
36
65
  try {
37
66
  subscriber.next?.(value);
38
67
  } catch (err) {
39
- console.error('Observable subscriber error:', err);
68
+ this.logError('Observable subscriber error', err);
40
69
  }
41
70
  }
42
71
  }
@@ -49,7 +78,7 @@ export class Observable<T> {
49
78
  try {
50
79
  subscriber.error?.(err);
51
80
  } catch (e) {
52
- console.error('Observable error handler failed:', e);
81
+ this.logError('Observable error handler failed', e);
53
82
  }
54
83
  }
55
84
  }
@@ -62,7 +91,7 @@ export class Observable<T> {
62
91
  try {
63
92
  subscriber.complete?.();
64
93
  } catch (err) {
65
- console.error('Observable complete handler failed:', err);
94
+ this.logError('Observable complete handler failed', err);
66
95
  }
67
96
  }
68
97
  this.subscribers.clear();