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,788 @@
1
+ # External Research: Incremental Tree Mutation Handling
2
+
3
+ **Research Date:** 2026-01-12
4
+ **Purpose:** P1M3T2S2 - Implement incremental node map updates for WorkflowTreeDebugger
5
+ **Focus:** BFS/DFS traversal, Map performance, event dispatching, and tree mutation patterns
6
+
7
+ ---
8
+
9
+ ## 1. React's Reconciliation & Virtual DOM Patterns
10
+
11
+ ### 1.1 Key Concepts from React's Diffing Algorithm
12
+
13
+ React's reconciliation algorithm provides excellent patterns for incremental tree updates:
14
+
15
+ **O(n) Algorithm for Tree Diffing:**
16
+ - React assumes two trees of different elements will produce different trees
17
+ - Uses heuristics to reduce O(n³) problem to O(n)
18
+ - Key heuristic: If elements have different types, entire subtrees are different
19
+
20
+ **Source:** [React Documentation - Reconciliation](https://react.dev/learn/render-and-commit)
21
+ - **Section:** "React's Diffing Algorithm"
22
+ - **Key Pattern:** Component type comparison for subtree replacement decisions
23
+
24
+ ### 1.2 Applicable Patterns for Tree Debugger
25
+
26
+ **Pattern 1: Key-based Identification**
27
+ ```typescript
28
+ // React uses keys to identify nodes across renders
29
+ // Similarly, nodeMap uses node.id for O(1) lookups
30
+
31
+ // Current implementation (good):
32
+ private nodeMap: Map<string, WorkflowNode> = new Map();
33
+
34
+ // Pattern: Always use stable identifiers for tree nodes
35
+ // Avoid using array indices as identifiers (breaks on insertions/deletions)
36
+ ```
37
+
38
+ **Pattern 2: Structural Change Detection**
39
+ ```typescript
40
+ // React detects structural changes by comparing element types
41
+ // For tree debugger, detect structural changes by event type:
42
+
43
+ onEvent(event: WorkflowEvent): void {
44
+ switch (event.type) {
45
+ case 'childAttached':
46
+ // Incremental: Add only new subtree
47
+ this.addSubtreeToMap(event.child);
48
+ break;
49
+ case 'childDetached':
50
+ // Incremental: Remove only detached subtree
51
+ this.removeSubtreeFromMap(event.child);
52
+ break;
53
+ default:
54
+ // Non-structural: No map update needed
55
+ break;
56
+ }
57
+ }
58
+ ```
59
+
60
+ **Pattern 3: Batching Updates**
61
+ ```typescript
62
+ // React batches multiple state updates
63
+ // Apply similar pattern for rapid tree changes:
64
+
65
+ private pendingUpdates: Array<() => void> = [];
66
+ private updateScheduled = false;
67
+
68
+ private scheduleUpdate(fn: () => void) {
69
+ this.pendingUpdates.push(fn);
70
+ if (!this.updateScheduled) {
71
+ this.updateScheduled = true;
72
+ Promise.resolve().then(() => {
73
+ this.pendingUpdates.forEach(fn => fn());
74
+ this.pendingUpdates = [];
75
+ this.updateScheduled = false;
76
+ });
77
+ }
78
+ }
79
+ ```
80
+
81
+ ### 1.3 Virtual DOM Memory Efficiency
82
+
83
+ **Insights:**
84
+ - Virtual DOM uses object pooling for frequently created objects
85
+ - Consider object pooling for WorkflowEvent if many events are created
86
+ - Use structural sharing: Only copy changed branches
87
+
88
+ ---
89
+
90
+ ## 2. JavaScript Map Manipulation & Performance
91
+
92
+ ### 2.1 MDN Map Best Practices
93
+
94
+ **Source:** [MDN Web Docs - Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)
95
+
96
+ **Key Performance Characteristics:**
97
+ - **Operations:** `set()`, `get()`, `has()`, `delete()` are O(1) average case
98
+ - **Iteration:** `forEach()` and `for...of` are optimized by V8
99
+ - **Memory:** Maps have slightly more overhead than Objects, but better for频繁添加/删除
100
+
101
+ ### 2.2 V8 Engine Optimizations
102
+
103
+ **Source:** [V8 Blog - Map Performance](https://v8.dev/blog/elements-kinds) (Related concepts)
104
+
105
+ **Optimization Patterns:**
106
+
107
+ **Pattern 1: Preserve Map Reference**
108
+ ```typescript
109
+ // BAD: Creates new Map frequently
110
+ function updateNodeMap(nodes: WorkflowNode[]): Map<string, WorkflowNode> {
111
+ const newMap = new Map();
112
+ nodes.forEach(node => newMap.set(node.id, node));
113
+ return newMap; // Forces garbage collection of old Map
114
+ }
115
+
116
+ // GOOD: Mutate existing Map
117
+ function addNodesToMap(map: Map<string, WorkflowNode>, nodes: WorkflowNode[]): void {
118
+ nodes.forEach(node => map.set(node.id, node));
119
+ }
120
+ ```
121
+
122
+ **Pattern 2: Batch Deletions**
123
+ ```typescript
124
+ // GOOD: Delete multiple keys in single iteration
125
+ function removeNodes(map: Map<string, WorkflowNode>, idsToRemove: string[]): void {
126
+ for (const id of idsToRemove) {
127
+ map.delete(id);
128
+ }
129
+ // V8 optimizes consecutive deletions
130
+ }
131
+
132
+ // BETTER: Collect keys first, then delete
133
+ function removeSubtree(map: Map<string, WorkflowNode>, rootId: string): void {
134
+ const keysToDelete: string[] = [];
135
+
136
+ // First pass: collect all keys in subtree
137
+ const collectKeys = (node: WorkflowNode) => {
138
+ keysToDelete.push(node.id);
139
+ node.children.forEach(child => collectKeys(child));
140
+ };
141
+
142
+ const rootNode = map.get(rootId);
143
+ if (rootNode) {
144
+ collectKeys(rootNode);
145
+ }
146
+
147
+ // Second pass: delete all collected keys
148
+ for (const key of keysToDelete) {
149
+ map.delete(key);
150
+ }
151
+ }
152
+ ```
153
+
154
+ **Pattern 3: Use `has()` for Conditional Access**
155
+ ```typescript
156
+ // GOOD: Check before accessing
157
+ if (this.nodeMap.has(nodeId)) {
158
+ const node = this.nodeMap.get(nodeId);
159
+ // Use node
160
+ }
161
+
162
+ // ACCEPTABLE: Direct access with undefined check
163
+ const node = this.nodeMap.get(nodeId);
164
+ if (node) {
165
+ // Use node
166
+ }
167
+ ```
168
+
169
+ ### 2.3 Map vs Object for Tree Nodes
170
+
171
+ **Use Map when:**
172
+ - Keys are not strings/symbols
173
+ - Need to iterate in insertion order
174
+ - Frequent additions/removals
175
+ - Need to know size efficiently
176
+
177
+ **Use Object when:**
178
+ - Keys are strings/symbols
179
+ - Need JSON serialization
180
+ - Static set of keys
181
+ - Prototype safety concerns
182
+
183
+ **Decision:** Map is correct choice for nodeMap due to:
184
+ - Frequent additions/removals (childAttached/childDetached)
185
+ - O(1) size property
186
+ - No prototype pollution concerns
187
+
188
+ ---
189
+
190
+ ## 3. BFS vs DFS Traversal for Tree Operations
191
+
192
+ ### 3.1 Algorithm Comparison
193
+
194
+ | Aspect | BFS (Breadth-First) | DFS (Depth-First) |
195
+ |--------|---------------------|-------------------|
196
+ | **Strategy** | Level-by-level | Go deep, then backtrack |
197
+ | **Memory** | O(w) - max width | O(h) - max height |
198
+ | **Time** | O(V + E) | O(V + E) |
199
+ | **Implementation** | Queue | Stack (or recursion) |
200
+ | **Use Case** | Shortest path, level-order | Memory efficient for deep trees |
201
+
202
+ ### 3.2 When to Use BFS for Tree Operations
203
+
204
+ **Use BFS when:**
205
+ 1. **Removing subtrees** - Process parent before children (natural for removal)
206
+ 2. **Level-order statistics** - Need to process nodes by depth
207
+ 3. **Finding nearest nodes** - Shortest path in unweighted tree
208
+ 4. **Wide trees** - When width << height
209
+
210
+ **BFS Implementation for Subtree Removal:**
211
+ ```typescript
212
+ /**
213
+ * Remove subtree using BFS traversal
214
+ * Good for: Processing parent before children, level-by-level cleanup
215
+ */
216
+ private removeSubtreeBFS(rootId: string): void {
217
+ const queue: string[] = [rootId];
218
+ const keysToRemove: string[] = [];
219
+
220
+ // Collect all node IDs in subtree
221
+ while (queue.length > 0) {
222
+ const currentId = queue.shift()!;
223
+ const node = this.nodeMap.get(currentId);
224
+
225
+ if (node) {
226
+ keysToRemove.push(currentId);
227
+ // Add children to queue (BFS order)
228
+ node.children.forEach(child => queue.push(child.id));
229
+ }
230
+ }
231
+
232
+ // Remove all collected keys
233
+ for (const key of keysToRemove) {
234
+ this.nodeMap.delete(key);
235
+ }
236
+ }
237
+ ```
238
+
239
+ ### 3.3 When to Use DFS for Tree Operations
240
+
241
+ **Use DFS when:**
242
+ 1. **Adding subtrees** - Recursively add children
243
+ 2. **Deep trees** - When height << width (memory efficient)
244
+ 3. **Path finding** - Need specific path between nodes
245
+ 4. **Ancestry checks** - Bottom-up processing
246
+
247
+ **DFS Implementation for Subtree Addition:**
248
+ ```typescript
249
+ /**
250
+ * Add subtree using DFS traversal
251
+ * Good for: Memory efficient, natural recursion
252
+ */
253
+ private addSubtreeDFS(node: WorkflowNode): void {
254
+ this.nodeMap.set(node.id, node);
255
+
256
+ // Recursively add children (DFS - depth-first)
257
+ for (const child of node.children) {
258
+ this.addSubtreeDFS(child);
259
+ }
260
+ }
261
+ ```
262
+
263
+ ### 3.4 Recommended Pattern for Tree Debugger
264
+
265
+ **Hybrid Approach:**
266
+
267
+ ```typescript
268
+ /**
269
+ * Incremental update based on event type
270
+ * Uses optimal traversal for each operation
271
+ */
272
+ private updateNodeMapIncremental(event: WorkflowEvent): void {
273
+ switch (event.type) {
274
+ case 'childAttached':
275
+ // DFS for addition: Natural recursion, memory efficient
276
+ this.addSubtreeDFS(event.child);
277
+ break;
278
+
279
+ case 'childDetached':
280
+ // BFS for removal: Parent before children, clear ordering
281
+ this.removeSubtreeBFS(event.child.id);
282
+ break;
283
+
284
+ default:
285
+ // Other events don't affect structure
286
+ break;
287
+ }
288
+ }
289
+ ```
290
+
291
+ ### 3.5 Performance Comparison
292
+
293
+ **Benchmark Scenario:** Tree with 1000 nodes, removing 100-node subtree
294
+
295
+ | Method | Time Complexity | Memory | Notes |
296
+ |--------|----------------|--------|-------|
297
+ | Full Rebuild | O(n) | O(n) | Clears all, re-adds all |
298
+ | BFS Incremental | O(m) | O(w) | m=subtree size, w=max width |
299
+ | DFS Incremental | O(m) | O(h) | m=subtree size, h=max height |
300
+
301
+ **Recommendation:** BFS for removal, DFS for addition
302
+
303
+ ---
304
+
305
+ ## 4. Memory Management Patterns for Tree Structures
306
+
307
+ ### 4.1 Weak References for Auxiliary Data
308
+
309
+ **Source:** [MDN - WeakMap](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)
310
+
311
+ **Pattern:** Use WeakMap for metadata that shouldn't prevent garbage collection
312
+
313
+ ```typescript
314
+ // Good pattern: WeakMap for node metadata
315
+ const nodeMetadata = new WeakMap<WorkflowNode, {
316
+ lastAccessed: number;
317
+ accessCount: number;
318
+ }>();
319
+
320
+ // When node is garbage collected, metadata is automatically cleaned up
321
+ // No memory leaks from detached nodes
322
+ ```
323
+
324
+ **Not Applicable to nodeMap:** nodeMap needs strong references (nodes must stay in memory)
325
+
326
+ ### 4.2 Circular Reference Prevention
327
+
328
+ **Common Pitfall:** Parent <-> Child circular references prevent garbage collection
329
+
330
+ ```typescript
331
+ // BAD: Circular references prevent GC
332
+ class TreeNode {
333
+ parent: TreeNode | null = null;
334
+ children: TreeNode[] = [];
335
+ }
336
+
337
+ // Even after removing from tree, nodes may stay in memory
338
+ // due to circular parent/child references
339
+
340
+ // Solution: Explicit cleanup
341
+ class TreeNode {
342
+ dispose() {
343
+ this.children.forEach(child => {
344
+ child.parent = null; // Break circular reference
345
+ child.dispose();
346
+ });
347
+ this.children = [];
348
+ }
349
+ }
350
+ ```
351
+
352
+ **For Tree Debugger:** Ensure detached nodes are removed from nodeMap
353
+
354
+ ```typescript
355
+ private removeSubtreeWithCleanup(rootId: string): void {
356
+ const node = this.nodeMap.get(rootId);
357
+ if (!node) return;
358
+
359
+ // Break references if needed (implementation dependent)
360
+ // For WorkflowNode, just remove from map
361
+ this.removeSubtreeBFS(rootId);
362
+ }
363
+ ```
364
+
365
+ ### 4.3 Object Pooling for Frequent Creation
366
+
367
+ **Pattern:** Reuse objects instead of creating/destroying
368
+
369
+ ```typescript
370
+ // Object pool for frequently created WorkflowEvent objects
371
+ class EventPool {
372
+ private pool: WorkflowEvent[] = [];
373
+
374
+ acquire(): WorkflowEvent {
375
+ return this.pool.pop() || this.createEvent();
376
+ }
377
+
378
+ release(event: WorkflowEvent): void {
379
+ // Reset event state
380
+ this.pool.push(event);
381
+ }
382
+
383
+ private createEvent(): WorkflowEvent {
384
+ // Create new event
385
+ return {} as WorkflowEvent;
386
+ }
387
+ }
388
+ ```
389
+
390
+ **When to Use:**
391
+ - High-frequency events (1000+ per second)
392
+ - Events have consistent structure
393
+ - Memory pressure is a concern
394
+
395
+ **For Tree Debugger:** Probably not needed unless event frequency is very high
396
+
397
+ ### 4.4 Memory Profiling Patterns
398
+
399
+ **Chrome DevTools Memory Profiling:**
400
+ ```typescript
401
+ // Add memory tracking for debugging
402
+ class MemoryTracker {
403
+ private snapshots: Map<string, number> = new Map();
404
+
405
+ snapshot(label: string): void {
406
+ if (performance.memory) {
407
+ this.snapshots.set(label, performance.memory.usedJSHeapSize);
408
+ }
409
+ }
410
+
411
+ report(): void {
412
+ console.table(this.snapshots);
413
+ }
414
+ }
415
+
416
+ // Usage in tree debugger
417
+ constructor(workflow: Workflow) {
418
+ this.memoryTracker = new MemoryTracker();
419
+ this.memoryTracker.snapshot('constructor');
420
+
421
+ // ... build node map
422
+
423
+ this.memoryTracker.snapshot('after-build');
424
+ }
425
+ ```
426
+
427
+ ---
428
+
429
+ ## 5. Common Pitfalls in Incremental Tree Updates
430
+
431
+ ### 5.1 Pitfall 1: Missing Descendants
432
+
433
+ **Problem:** Only removing/adding root node, not entire subtree
434
+
435
+ ```typescript
436
+ // BAD: Only removes root
437
+ private removeSubtreeBad(rootId: string): void {
438
+ this.nodeMap.delete(rootId); // Children remain in map!
439
+ }
440
+
441
+ // GOOD: Removes entire subtree
442
+ private removeSubtreeGood(rootId: string): void {
443
+ const keysToDelete = this.collectSubtreeKeys(rootId);
444
+ for (const key of keysToDelete) {
445
+ this.nodeMap.delete(key);
446
+ }
447
+ }
448
+
449
+ private collectSubtreeKeys(rootId: string): string[] {
450
+ const keys: string[] = [];
451
+ const queue = [rootId];
452
+
453
+ while (queue.length > 0) {
454
+ const currentId = queue.shift()!;
455
+ const node = this.nodeMap.get(currentId);
456
+
457
+ if (node) {
458
+ keys.push(currentId);
459
+ node.children.forEach(child => queue.push(child.id));
460
+ }
461
+ }
462
+
463
+ return keys;
464
+ }
465
+ ```
466
+
467
+ ### 5.2 Pitfall 2: Inconsistent State During Update
468
+
469
+ **Problem:** Map is partially updated when accessed by other code
470
+
471
+ ```typescript
472
+ // BAD: Map is inconsistent during iteration
473
+ private removeSubtreeBad(rootId: string): void {
474
+ const node = this.nodeMap.get(rootId);
475
+ if (node) {
476
+ this.nodeMap.delete(rootId); // Map now missing root
477
+ // If another thread calls getNode() here, returns undefined
478
+ node.children.forEach(child => {
479
+ this.removeSubtreeBad(child.id); // Recursion leaves map inconsistent
480
+ });
481
+ }
482
+ }
483
+
484
+ // GOOD: Collect all keys first, then update atomically
485
+ private removeSubtreeGood(rootId: string): void {
486
+ const keysToDelete = this.collectSubtreeKeys(rootId);
487
+
488
+ // Single atomic update
489
+ for (const key of keysToDelete) {
490
+ this.nodeMap.delete(key);
491
+ }
492
+ }
493
+ ```
494
+
495
+ ### 5.3 Pitfall 3: Event Type Confusion
496
+
497
+ **Problem:** Treating all events as structural changes
498
+
499
+ ```typescript
500
+ // BAD: Rebuilds on every event
501
+ onEvent(event: WorkflowEvent): void {
502
+ this.nodeMap.clear();
503
+ this.buildNodeMap(this.root); // Unnecessary for non-structural events
504
+ }
505
+
506
+ // GOOD: Only update on structural changes
507
+ onEvent(event: WorkflowEvent): void {
508
+ switch (event.type) {
509
+ case 'childAttached':
510
+ this.addSubtreeDFS(event.child);
511
+ break;
512
+ case 'childDetached':
513
+ this.removeSubtreeBFS(event.child.id);
514
+ break;
515
+ // Other events don't affect structure
516
+ }
517
+ }
518
+ ```
519
+
520
+ ### 5.4 Pitfall 4: Stack Overflow on Deep Recursion
521
+
522
+ **Problem:** DFS recursion on very deep trees causes stack overflow
523
+
524
+ ```typescript
525
+ // BAD: Recursion may overflow stack on deep trees
526
+ private addSubtreeDFS(node: WorkflowNode): void {
527
+ this.nodeMap.set(node.id, node);
528
+ node.children.forEach(child => this.addSubtreeDFS(child)); // Recursion depth = tree height
529
+ }
530
+
531
+ // GOOD: Use iterative DFS for deep trees
532
+ private addSubtreeDFSIterative(node: WorkflowNode): void {
533
+ const stack = [node];
534
+
535
+ while (stack.length > 0) {
536
+ const current = stack.pop()!;
537
+ this.nodeMap.set(current.id, current);
538
+
539
+ // Push children in reverse order for correct traversal
540
+ for (let i = current.children.length - 1; i >= 0; i--) {
541
+ stack.push(current.children[i]);
542
+ }
543
+ }
544
+ }
545
+ ```
546
+
547
+ **Recommendation:** Use iterative approach for production code with unknown tree depth
548
+
549
+ ### 5.5 Pitfall 5: Memory Leaks from Event Listeners
550
+
551
+ **Problem:** Observers not removed when workflow is destroyed
552
+
553
+ ```typescript
554
+ // BAD: Observer never removed
555
+ class WorkflowTreeDebugger {
556
+ constructor(workflow: Workflow) {
557
+ workflow.addObserver(this); // Never removed
558
+ }
559
+ }
560
+
561
+ // GOOD: Implement cleanup
562
+ class WorkflowTreeDebugger {
563
+ constructor(private workflow: Workflow) {
564
+ this.workflow.addObserver(this);
565
+ }
566
+
567
+ dispose(): void {
568
+ this.workflow.removeObserver(this);
569
+ this.nodeMap.clear();
570
+ }
571
+ }
572
+ ```
573
+
574
+ ---
575
+
576
+ ## 6. Actionable Implementation Guide
577
+
578
+ ### 6.1 Implement removeSubtreeNodes() with BFS
579
+
580
+ ```typescript
581
+ /**
582
+ * Remove subtree nodes from nodeMap using BFS traversal
583
+ * @param rootId ID of root node to remove
584
+ *
585
+ * Why BFS:
586
+ * - Processes parent before children (natural removal order)
587
+ * - Level-by-level traversal predictable
588
+ * - No recursion (no stack overflow risk)
589
+ */
590
+ private removeSubtreeNodes(rootId: string): void {
591
+ const queue: string[] = [rootId];
592
+ const keysToRemove: string[] = [];
593
+
594
+ // BFS traversal to collect all keys in subtree
595
+ while (queue.length > 0) {
596
+ const currentId = queue.shift()!;
597
+ const node = this.nodeMap.get(currentId);
598
+
599
+ if (node) {
600
+ keysToRemove.push(currentId);
601
+ // Add children to queue for BFS traversal
602
+ node.children.forEach(child => queue.push(child.id));
603
+ }
604
+ }
605
+
606
+ // Batch delete all collected keys
607
+ for (const key of keysToRemove) {
608
+ this.nodeMap.delete(key);
609
+ }
610
+ }
611
+ ```
612
+
613
+ ### 6.2 Implement Event-Type Dispatch for onEvent()
614
+
615
+ ```typescript
616
+ /**
617
+ * Handle workflow events with type-based dispatch
618
+ * @param event Workflow event to process
619
+ *
620
+ * Performance considerations:
621
+ * - Only updates nodeMap on structural changes
622
+ * - Non-structural events bypass map updates
623
+ * - O(1) switch statement dispatch
624
+ */
625
+ onEvent(event: WorkflowEvent): void {
626
+ // Early return for non-structural events (fast path)
627
+ if (event.type !== 'childAttached' && event.type !== 'childDetached') {
628
+ this.events.next(event);
629
+ return;
630
+ }
631
+
632
+ // Type-based dispatch for structural events
633
+ switch (event.type) {
634
+ case 'childAttached': {
635
+ // Incremental add: DFS for memory efficiency
636
+ this.addSubtreeDFS(event.child);
637
+ break;
638
+ }
639
+
640
+ case 'childDetached': {
641
+ // Incremental remove: BFS for level-by-level cleanup
642
+ this.removeSubtreeNodes(event.child.id);
643
+ break;
644
+ }
645
+
646
+ default: {
647
+ // Exhaustive check for type safety
648
+ const _exhaustiveCheck: never = event;
649
+ break;
650
+ }
651
+ }
652
+
653
+ // Forward all events to event stream
654
+ this.events.next(event);
655
+ }
656
+
657
+ /**
658
+ * Add subtree using DFS traversal
659
+ * Good for: Memory efficient on deep trees, natural recursion
660
+ */
661
+ private addSubtreeDFS(node: WorkflowNode): void {
662
+ this.nodeMap.set(node.id, node);
663
+ node.children.forEach(child => this.addSubtreeDFS(child));
664
+ }
665
+ ```
666
+
667
+ ### 6.3 Performance Optimization Checklist
668
+
669
+ **Optimizations Applied:**
670
+ - [x] Use Map instead of Object for O(1) operations
671
+ - [x] Batch deletions (collect keys, then delete)
672
+ - [x] Event-type dispatch (avoid unnecessary updates)
673
+ - [x] BFS for removal (parent before children)
674
+ - [x] DFS for addition (memory efficient)
675
+ - [ ] Consider iterative DFS for very deep trees
676
+ - [ ] Add memory tracking for debugging
677
+ - [ ] Consider batching rapid successive updates
678
+
679
+ **Future Optimizations:**
680
+ - Object pooling for high-frequency events
681
+ - WeakMap for auxiliary metadata
682
+ - Update batching/debouncing for rapid changes
683
+ - Lazy nodeMap rebuild after N incremental updates
684
+
685
+ ### 6.4 Testing Strategy
686
+
687
+ ```typescript
688
+ describe('Incremental Node Map Updates', () => {
689
+ it('should correctly remove subtree using BFS', () => {
690
+ const debugger = new WorkflowTreeDebugger(rootWorkflow);
691
+
692
+ // Build tree with 100 nodes
693
+ const initialSize = debugger.getStats().totalNodes;
694
+ expect(initialSize).toBe(100);
695
+
696
+ // Detach subtree with 20 nodes
697
+ detachChild(childId);
698
+
699
+ // Verify only 20 nodes removed
700
+ const finalSize = debugger.getStats().totalNodes;
701
+ expect(finalSize).toBe(80);
702
+
703
+ // Verify detached nodes not accessible
704
+ expect(debugger.getNode(detachedChildId)).toBeUndefined();
705
+ expect(debugger.getNode(detachedGrandchildId)).toBeUndefined();
706
+ });
707
+
708
+ it('should correctly add subtree using DFS', () => {
709
+ const debugger = new WorkflowTreeDebugger(rootWorkflow);
710
+
711
+ // Attach subtree with 20 nodes
712
+ attachChild(parentId, newChild);
713
+
714
+ // Verify all 20 nodes added
715
+ const stats = debugger.getStats();
716
+ expect(stats.totalNodes).toBe(120);
717
+
718
+ // Verify all nodes accessible
719
+ expect(debugger.getNode(newChild.id)).toBeDefined();
720
+ expect(debugger.getNode(grandchild.id)).toBeDefined();
721
+ });
722
+
723
+ it('should handle non-structural events efficiently', () => {
724
+ const debugger = new WorkflowTreeDebugger(rootWorkflow);
725
+ const initialMapSize = (debugger as any).nodeMap.size;
726
+
727
+ // Trigger 100 non-structural events
728
+ for (let i = 0; i < 100; i++) {
729
+ triggerNonStructuralEvent();
730
+ }
731
+
732
+ // Verify nodeMap not rebuilt
733
+ expect((debugger as any).nodeMap.size).toBe(initialMapSize);
734
+ });
735
+ });
736
+ ```
737
+
738
+ ---
739
+
740
+ ## 7. Summary & Recommendations
741
+
742
+ ### 7.1 Key Takeaways
743
+
744
+ 1. **Use BFS for subtree removal** - Parent before children, predictable ordering
745
+ 2. **Use DFS for subtree addition** - Memory efficient, natural recursion
746
+ 3. **Event-type dispatch** - Only update map on structural changes
747
+ 4. **Batch operations** - Collect keys, then update atomically
748
+ 5. **Consider iterative DFS** - Avoid stack overflow on deep trees
749
+
750
+ ### 7.2 Performance Improvements
751
+
752
+ **Before (Full Rebuild):**
753
+ - Time: O(n) for every tree change
754
+ - Memory: O(n) - entire tree in memory during rebuild
755
+ - Scalability: Poor for large trees
756
+
757
+ **After (Incremental):**
758
+ - Time: O(m) where m = subtree size
759
+ - Memory: O(w) for BFS, O(h) for DFS
760
+ - Scalability: Excellent for large trees
761
+
762
+ **Expected Speedup:** 10-100x for large trees when modifying small subtrees
763
+
764
+ ### 7.3 References
765
+
766
+ 1. **React Reconciliation:** https://react.dev/learn/render-and-commit
767
+ - Section: "React's Diffing Algorithm"
768
+ - Key concepts: O(n) heuristics, key-based identification
769
+
770
+ 2. **MDN Map Documentation:** https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
771
+ - Operations: O(1) get/set/has/delete
772
+ - Iteration: forEach and for...of performance
773
+
774
+ 3. **V8 Performance Blog:** https://v8.dev/blog
775
+ - Map optimization patterns
776
+ - Hidden classes and inline caching
777
+
778
+ 4. **WeakMap Documentation:** https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
779
+ - Use case: Auxiliary data that shouldn't prevent GC
780
+
781
+ 5. **Chrome DevTools Memory:** https://developer.chrome.com/docs/devtools/memory-problems
782
+ - Heap snapshots, memory profiling
783
+
784
+ ---
785
+
786
+ **Document Status:** Research Complete
787
+ **Next Step:** Implement incremental updates in WorkflowTreeDebugger
788
+ **Estimated Impact:** 10-100x performance improvement for large tree operations