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.
- package/.claude/commands/subtask-planning/prp-base-create.md +120 -0
- package/.claude/commands/subtask-planning/prp-base-execute.md +65 -0
- package/.claude/commands/task-breakdown.md +94 -0
- package/.claude/system_prompts/task-breakdown.md +1 -0
- package/CHANGELOG.md +188 -0
- package/PRD.md +543 -0
- package/README.md +99 -5
- package/examples/README.md +15 -1
- package/examples/examples/11-reparenting-workflows.ts +269 -0
- package/examples/index.ts +4 -0
- package/package-lock.json +2398 -0
- package/package.json +3 -1
- package/plan/001_d3bb02af4886/TEST_RESULTS.md +259 -0
- package/plan/001_d3bb02af4886/bug_fix_tasks.json +484 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S1/PRP.md +488 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S2/PRP.md +581 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S3/PRP.md +687 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S1/PRP.md +492 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/PRP.md +932 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/concurrent_error_testing_patterns.md +1109 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/vitest_concurrent_testing.md +802 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/workflow_engine_test_references.md +603 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S1/PRP.md +564 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S3/PRP.md +518 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S4/PRP.md +1252 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/PRP.md +364 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/CODEBASE_INVENTORY.md +114 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/DECORATOR_DOCUMENTATION_PATTERNS.md +205 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/PRD_LOCATION_ANALYSIS.md +199 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/ULTRATHINK_PRP_PLAN.md +134 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/PRP.md +495 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/research/console_error_inventory.md +435 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S2/PRP.md +506 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S3/PRP.md +612 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/PRP.md +558 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/research/external_research.md +788 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S2/PRP.md +460 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S3/PRP.md +454 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/PRP.md +520 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/RECOMMENDATION.md +417 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/external_workflow_engines_research.md +760 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/security_implications_analysis.md +245 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S2/PRP.md +792 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/PRP.md +535 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/TEST_EXECUTION_REPORT.md +190 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/PRP.md +654 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/TEST_FIX_REPORT.md +227 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/KEY_FINDINGS.md +345 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/QUICK_REFERENCE.md +193 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/test_maintenance_research.md +1323 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/BREAKING_CHANGES_AUDIT.md +1011 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/PRP.md +927 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S2/PRP.md +505 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/architecture/logger_child_signature_analysis.md +401 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/child_implementation_research.md +142 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/test_patterns_research.md +112 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/vitest_patterns_research.md +159 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/PRP.md +549 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/VERIFICATION_REPORT.md +368 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/edge_case_analysis.md +172 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/usage_inventory.md +175 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S2/PRP.md +696 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S4/PRP.md +860 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/PRP.md +1066 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01-testing-aggregated-errors.md +1103 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01_typescript_error_aggregation_patterns.md +789 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02-error-merge-strategy-testing-guide.md +1098 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02_aggregate_error_patterns.md +1037 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03-promise-allsettled-testing-patterns.md +916 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03_error_merging_strategies.md +1045 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/04_github_stackoverflow_examples.md +890 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/05_comprehensive_summary.md +822 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/INDEX.md +668 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/QUICK_REFERENCE.md +706 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/README.md +265 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/RESEARCH_REPORT.md +655 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S4/research/vitest_testing_patterns.md +1103 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T3S2/PRP.md +426 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/PRP.md +506 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/QUICK_REFERENCE.md +114 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/RESEARCH_SUMMARY.md +316 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/vitest_observer_error_logging_best_practices.md +754 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S3/PRP.md +612 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/PRP.md +719 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/README.md +215 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/analysis.md +765 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S3/PRP.md +718 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/DECISION.md +149 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/PRP.md +470 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/ULTRATHINK_PLAN.md +332 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/codebase_workflow_name_analysis.md +167 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/external_best_practices.md +265 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/validation_patterns.md +273 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S1/workflow_engine_ancestry_api_research.md +760 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S3-PRP.md +434 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S1/PRP.md +717 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/PRP.md +472 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/VALIDATION_REPORT.md +125 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/research/ULTRATHINK_PRP_PLAN.md +301 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/error-logging-best-practices.md +1170 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/research_typescript_partial_and_overloads.md +940 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-quick-reference.md +151 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-research.md +650 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/prd_snapshot.md +259 -0
- package/plan/001_d3bb02af4886/bugfix/P1M1T1S1/PRP.md +457 -0
- package/plan/001_d3bb02af4886/bugfix/RESEARCH_SUMMARY.md +346 -0
- package/plan/001_d3bb02af4886/bugfix/architecture/codebase_structure.md +311 -0
- package/plan/001_d3bb02af4886/bugfix/architecture/concurrent_execution_best_practices.md +1565 -0
- package/plan/001_d3bb02af4886/bugfix/architecture/error_handling_patterns.md +288 -0
- package/plan/001_d3bb02af4886/bugfix/architecture/promise_all_analysis.md +741 -0
- package/plan/001_d3bb02af4886/docs/PRP/P1M1T1S4-functional-workflow-error-state-capture-test.md +652 -0
- package/plan/001_d3bb02af4886/docs/PRP/PRP.md +527 -0
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S1-PRP.md +415 -0
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S2-PRP.md +378 -0
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S4-PRP.md +713 -0
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M2T1S4-PRP.md +370 -0
- package/plan/001_d3bb02af4886/docs/PRP_P1M3T1S3.md +499 -0
- package/plan/001_d3bb02af4886/docs/TEST_RESULTS.md +230 -0
- package/plan/001_d3bb02af4886/docs/bugfix/ANALYSIS_PRD_VS_IMPLEMENTATION.md +1134 -0
- package/plan/001_d3bb02af4886/docs/bugfix/GAP_ANALYSIS_SUMMARY.md +179 -0
- package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/PRP.md +629 -0
- package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/validation-report.md +214 -0
- package/plan/001_d3bb02af4886/docs/bugfix/PRP_P1M4T2S3.md +629 -0
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_PRP.md +529 -0
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_QUICK_REFERENCE.md +142 -0
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_README.md +304 -0
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_TEST_RESULTS.md +558 -0
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_VALIDATION_SUMMARY.md +256 -0
- package/plan/001_d3bb02af4886/docs/bugfix/system_context.md +346 -0
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/bug_analysis.md +415 -0
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/implementation_patterns.md +489 -0
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/system_context.md +218 -0
- package/plan/001_d3bb02af4886/docs/bugfix_INITIATION_SUMMARY.md +380 -0
- package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_PATTERNS.md +1923 -0
- package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_QUICK_REF.md +319 -0
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/codebase-context.md +115 -0
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/cycle-detection-algorithms.md +134 -0
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/test-patterns.md +153 -0
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/workflow-class.md +132 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_BEST_PRACTICES.md +716 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_QUICK_REF.md +186 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/GROUNDSWELL_DECORATOR_EXAMPLES.md +604 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/INDEX.md +213 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/codebase_structure.md +30 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/existing_test_pattern.md +56 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/getRootObservers_implementation.md +53 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/test_conventions.md +49 -0
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/PRP.md +958 -0
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/QUICK_REFERENCE.md +339 -0
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/README.md +305 -0
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/SUMMARY.md +433 -0
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/bidirectional-tree-consistency-testing.md +1574 -0
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/test-pattern-examples.md +1014 -0
- package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_QUICK_REF.md +376 -0
- package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_RESEARCH.md +1507 -0
- package/plan/001_d3bb02af4886/docs/research/bugfix_typescript_patterns.md +949 -0
- package/plan/001_d3bb02af4886/docs/research/error-testing-research.md +619 -0
- package/plan/001_d3bb02af4886/docs/research/error_handling_patterns.md +723 -0
- package/plan/{research → 001_d3bb02af4886/docs/research/general}/introspection-security-guide.md +56 -0
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/PRP_TEMPLATE.md +460 -0
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/QUICK_REFERENCE.md +324 -0
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/README.md +175 -0
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/RESEARCH_REPORT.md +499 -0
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/SUMMARY.md +163 -0
- package/plan/bugfix/BUG_FIX_SUMMARY.md +961 -0
- package/src/__tests__/adversarial/attachChild-performance.test.ts +216 -0
- package/src/__tests__/adversarial/circular-reference.test.ts +101 -0
- package/src/__tests__/adversarial/complex-circular-reference.test.ts +139 -0
- package/src/__tests__/adversarial/concurrent-task-failures.test.ts +571 -0
- package/src/__tests__/adversarial/deep-analysis.test.ts +729 -0
- package/src/__tests__/adversarial/deep-hierarchy-stress.test.ts +213 -0
- package/src/__tests__/adversarial/e2e-prd-validation.test.ts +448 -0
- package/src/__tests__/adversarial/edge-case.test.ts +703 -0
- package/src/__tests__/adversarial/error-merge-strategy.test.ts +760 -0
- package/src/__tests__/adversarial/incremental-performance.test.ts +140 -0
- package/src/__tests__/adversarial/node-map-update-benchmarks.test.ts +457 -0
- package/src/__tests__/adversarial/observer-propagation.test.ts +487 -0
- package/src/__tests__/adversarial/parent-validation.test.ts +143 -0
- package/src/__tests__/adversarial/prd-12-2-compliance.test.ts +611 -0
- package/src/__tests__/adversarial/prd-compliance.test.ts +731 -0
- package/src/__tests__/compatibility/backward-compatibility.test.ts +1572 -0
- package/src/__tests__/helpers/index.ts +18 -0
- package/src/__tests__/helpers/tree-verification.ts +257 -0
- package/src/__tests__/integration/bidirectional-consistency.test.ts +847 -0
- package/src/__tests__/integration/observer-logging.test.ts +643 -0
- package/src/__tests__/integration/tree-mirroring.test.ts +37 -0
- package/src/__tests__/integration/workflow-reparenting.test.ts +303 -0
- package/src/__tests__/unit/context.test.ts +79 -0
- package/src/__tests__/unit/logger.test.ts +293 -0
- package/src/__tests__/unit/observable.test.ts +321 -0
- package/src/__tests__/unit/tree-debugger-incremental.test.ts +170 -0
- package/src/__tests__/unit/utils/workflow-error-utils.test.ts +209 -0
- package/src/__tests__/unit/workflow-detachChild.test.ts +100 -0
- package/src/__tests__/unit/workflow-emitEvent-childDetached.test.ts +153 -0
- package/src/__tests__/unit/workflow-isDescendantOf.test.ts +180 -0
- package/src/__tests__/unit/workflow.test.ts +277 -1
- package/src/core/agent.ts +21 -1
- package/src/core/logger.ts +27 -2
- package/src/core/workflow-context.ts +6 -4
- package/src/core/workflow.ts +252 -14
- package/src/debugger/tree-debugger.ts +52 -7
- package/src/decorators/task.ts +65 -2
- package/src/index.ts +4 -2
- package/src/types/decorators.ts +8 -1
- package/src/types/events.ts +1 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/observable.ts +32 -3
- package/src/utils/workflow-error-utils.ts +56 -0
- package/tsconfig.json +1 -1
- package/llms_full.txt +0 -5890
- package/tasks.json +0 -0
- /package/plan/{backlog.json → 001_d3bb02af4886/backlog.json} +0 -0
- /package/plan/{P1P2/PRP.md → 001_d3bb02af4886/docs/PRP/P1P2-PRP.md} +0 -0
- /package/plan/{P3P4/PRP.md → 001_d3bb02af4886/docs/PRP/P3P4-PRP.md} +0 -0
- /package/plan/{P4P5/PRP.md → 001_d3bb02af4886/docs/PRP/P4P5-PRP.md} +0 -0
- /package/plan/{architecture → 001_d3bb02af4886/docs/architecture}/external_deps.md +0 -0
- /package/plan/{architecture → 001_d3bb02af4886/docs/architecture}/system_context.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/LRU_CACHE_BEST_PRACTICES.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/LRU_CACHE_CODE_PATTERNS.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/LRU_CACHE_INTEGRATION_GUIDE.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/LRU_CACHE_RESEARCH_INDEX.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/REFLECTION_INDEX.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/REFLECTION_RESEARCH_REPORT.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/RESEARCH_SUMMARY.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/anthropic-sdk.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/async-local-storage.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-code-patterns.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-decision-matrix.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-implementation-guide.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-integration-guide.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-patterns.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-quick-reference.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/zod-schema.md +0 -0
- /package/plan/{P3P4/research → 001_d3bb02af4886/docs/research/P3P4}/caching-lru.md +0 -0
- /package/plan/{P3P4/research → 001_d3bb02af4886/docs/research/P3P4}/introspection-tools.md +0 -0
- /package/plan/{P3P4/research → 001_d3bb02af4886/docs/research/P3P4}/reflection-patterns.md +0 -0
- /package/plan/{P4P5/research → 001_d3bb02af4886/docs/research/P4P5}/RESEARCH_SUMMARY.md +0 -0
- /package/plan/{research → 001_d3bb02af4886/docs/research/general}/INTROSPECTION_RESEARCH_SUMMARY.md +0 -0
- /package/plan/{research → 001_d3bb02af4886/docs/research/general}/README-INTROSPECTION.md +0 -0
- /package/plan/{research → 001_d3bb02af4886/docs/research/general}/agent-introspection-patterns.md +0 -0
- /package/plan/{research → 001_d3bb02af4886/docs/research/general}/introspection-tool-examples.md +0 -0
- /package/{PRPs/PRDs/001-hierarchical-workflow-engine.md → plan/001_d3bb02af4886/prd_snapshot.md} +0 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep Hierarchy Stress Tests
|
|
3
|
+
*
|
|
4
|
+
* These stress tests validate the Workflow class handles deep hierarchies (1000+ levels)
|
|
5
|
+
* without stack overflow or performance issues in getRoot() and isDescendantOf() methods.
|
|
6
|
+
*
|
|
7
|
+
* Pattern 8 from plan/docs/bugfix-architecture/implementation_patterns.md:
|
|
8
|
+
* "Test deep hierarchies (1000+ levels) to ensure no stack overflow in getRoot() or isDescendantOf()"
|
|
9
|
+
*
|
|
10
|
+
* Related: plan/bugfix/P1M3T1S1/PRP.md
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
14
|
+
import { Workflow } from '../../index.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* SimpleWorkflow class for testing
|
|
18
|
+
* Pattern from: src/__tests__/adversarial/circular-reference.test.ts:20-26
|
|
19
|
+
*/
|
|
20
|
+
class SimpleWorkflow extends Workflow {
|
|
21
|
+
async run(): Promise<string> {
|
|
22
|
+
this.setStatus('running');
|
|
23
|
+
this.setStatus('completed');
|
|
24
|
+
return 'done';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
describe('Deep Hierarchy Stress Tests', () => {
|
|
29
|
+
/**
|
|
30
|
+
* Setup: Mock console methods to capture error messages
|
|
31
|
+
* Pattern from: src/__tests__/adversarial/circular-reference.test.ts:33-37
|
|
32
|
+
*/
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
vi.spyOn(console, 'log').mockImplementation(() => {});
|
|
35
|
+
vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
36
|
+
vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Teardown: Restore all mocks to prevent test pollution
|
|
41
|
+
* CRITICAL: Always use vi.restoreAllMocks() in afterEach
|
|
42
|
+
* Pattern from: src/__tests__/adversarial/circular-reference.test.ts:43-45
|
|
43
|
+
*/
|
|
44
|
+
afterEach(() => {
|
|
45
|
+
vi.restoreAllMocks();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Test 1: Deep Hierarchy Creation (1000+ levels)
|
|
50
|
+
*
|
|
51
|
+
* Validates that a chain of 1000+ nested workflows can be created
|
|
52
|
+
* using loop iteration (not recursion to avoid test-side stack overflow).
|
|
53
|
+
*
|
|
54
|
+
* Pattern from: src/__tests__/adversarial/edge-case.test.ts:264-282
|
|
55
|
+
* Modified to test 1000+ levels instead of 100
|
|
56
|
+
*/
|
|
57
|
+
it('should create 1000+ level deep workflow hierarchy', () => {
|
|
58
|
+
const DEPTH = 1000;
|
|
59
|
+
let lastWorkflow: any = null;
|
|
60
|
+
|
|
61
|
+
for (let i = 0; i < DEPTH; i++) {
|
|
62
|
+
const name = `Workflow-${i}`;
|
|
63
|
+
|
|
64
|
+
// Use constructor with parent parameter for auto-attachment
|
|
65
|
+
// Pattern from: workflow.ts:113-116 (constructor auto-attaches when parent provided)
|
|
66
|
+
lastWorkflow = new SimpleWorkflow(name, lastWorkflow);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Verify hierarchy depth by walking parent chain
|
|
70
|
+
let depth = 0;
|
|
71
|
+
let current: any = lastWorkflow;
|
|
72
|
+
while (current.parent) {
|
|
73
|
+
depth++;
|
|
74
|
+
current = current.parent;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// depth should be DEPTH - 1 because root (first workflow) has no parent
|
|
78
|
+
expect(depth).toBe(DEPTH - 1);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Test 2: getRoot() Stress Test
|
|
83
|
+
*
|
|
84
|
+
* Validates that getRoot() can be called on the deepest child
|
|
85
|
+
* and returns the root workflow without stack overflow.
|
|
86
|
+
*
|
|
87
|
+
* getRoot() implementation at workflow.ts:184-212 uses iterative while loop
|
|
88
|
+
* with Set<Workflow> for cycle detection, so it should handle deep chains.
|
|
89
|
+
*
|
|
90
|
+
* CRITICAL: getRoot() is protected - must cast to 'any' for testing
|
|
91
|
+
*/
|
|
92
|
+
it('should call getRoot() on deepest child without stack overflow', () => {
|
|
93
|
+
const DEPTH = 1000;
|
|
94
|
+
const root = new SimpleWorkflow('Root');
|
|
95
|
+
let current: any = root;
|
|
96
|
+
|
|
97
|
+
// Build deep hierarchy using constructor with parent
|
|
98
|
+
for (let i = 0; i < DEPTH; i++) {
|
|
99
|
+
const child = new SimpleWorkflow(`Child-${i}`, current);
|
|
100
|
+
current = child;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// getRoot() is protected - cast to any
|
|
104
|
+
const foundRoot = (current as any).getRoot();
|
|
105
|
+
|
|
106
|
+
// Verify correct root returned
|
|
107
|
+
expect(foundRoot.id).toBe(root.id);
|
|
108
|
+
expect(foundRoot.node.name).toBe('Root');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Test 3: isDescendantOf() Stress Test
|
|
113
|
+
*
|
|
114
|
+
* Validates that isDescendantOf() can be called on deep chains
|
|
115
|
+
* without stack overflow.
|
|
116
|
+
*
|
|
117
|
+
* isDescendantOf() should use iterative while loop similar to getRoot()
|
|
118
|
+
* with cycle detection to handle deep chains safely.
|
|
119
|
+
*
|
|
120
|
+
* CRITICAL: isDescendantOf() is private - must cast to 'any' for testing
|
|
121
|
+
* CRITICAL: Test both positive and negative cases
|
|
122
|
+
*/
|
|
123
|
+
it('should call isDescendantOf() without stack overflow on deep hierarchy', () => {
|
|
124
|
+
const DEPTH = 1000;
|
|
125
|
+
const root = new SimpleWorkflow('Root');
|
|
126
|
+
let current: any = root;
|
|
127
|
+
|
|
128
|
+
// Build deep hierarchy
|
|
129
|
+
for (let i = 0; i < DEPTH; i++) {
|
|
130
|
+
const child = new SimpleWorkflow(`Child-${i}`, current);
|
|
131
|
+
current = child;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// isDescendantOf is private - cast to any
|
|
135
|
+
// Test positive case: deepest child IS descendant of root
|
|
136
|
+
const isDescendant = (current as any).isDescendantOf(root);
|
|
137
|
+
expect(isDescendant).toBe(true);
|
|
138
|
+
|
|
139
|
+
// Test negative case: root is NOT descendant of deepest child
|
|
140
|
+
const notDescendant = (root as any).isDescendantOf(current);
|
|
141
|
+
expect(notDescendant).toBe(false);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Test 4: Performance Threshold Test
|
|
146
|
+
*
|
|
147
|
+
* Validates that deep tree operations complete within acceptable time.
|
|
148
|
+
* Since getRoot() and isDescendantOf() use iterative algorithms,
|
|
149
|
+
* they should complete in < 100ms even for 1000-level deep chains.
|
|
150
|
+
*
|
|
151
|
+
* This test ensures O(n) iterative performance, not O(n) recursive overhead.
|
|
152
|
+
*/
|
|
153
|
+
it('should complete deep tree operations within acceptable time', () => {
|
|
154
|
+
const DEPTH = 1000;
|
|
155
|
+
const root = new SimpleWorkflow('Root');
|
|
156
|
+
let current: any = root;
|
|
157
|
+
|
|
158
|
+
// Build deep hierarchy
|
|
159
|
+
for (let i = 0; i < DEPTH; i++) {
|
|
160
|
+
current = new SimpleWorkflow(`Child-${i}`, current);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Measure getRoot() performance
|
|
164
|
+
const startTime = performance.now();
|
|
165
|
+
const foundRoot = (current as any).getRoot();
|
|
166
|
+
const getRootDuration = performance.now() - startTime;
|
|
167
|
+
|
|
168
|
+
expect(foundRoot.id).toBe(root.id);
|
|
169
|
+
expect(getRootDuration).toBeLessThan(100); // Should be very fast (< 100ms)
|
|
170
|
+
|
|
171
|
+
// Measure isDescendantOf() performance
|
|
172
|
+
const measureStart = performance.now();
|
|
173
|
+
const isDescendant = (current as any).isDescendantOf(root);
|
|
174
|
+
const checkDuration = performance.now() - measureStart;
|
|
175
|
+
|
|
176
|
+
expect(isDescendant).toBe(true);
|
|
177
|
+
expect(checkDuration).toBeLessThan(100); // Should be very fast (< 100ms)
|
|
178
|
+
|
|
179
|
+
// Total operations should complete well under 1 second
|
|
180
|
+
const totalStartTime = performance.now();
|
|
181
|
+
for (let i = 0; i < 100; i++) {
|
|
182
|
+
(current as any).getRoot();
|
|
183
|
+
(current as any).isDescendantOf(root);
|
|
184
|
+
}
|
|
185
|
+
const totalDuration = performance.now() - totalStartTime;
|
|
186
|
+
expect(totalDuration).toBeLessThan(1000); // 100 iterations in < 1 second
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Test 5: Extreme Deep Hierarchy (2000 levels)
|
|
191
|
+
*
|
|
192
|
+
* Tests an even deeper hierarchy to ensure safety margin.
|
|
193
|
+
* JavaScript V8 call stack is ~10,000-15,000 frames,
|
|
194
|
+
* so testing at 2000 levels provides a 20% safety margin.
|
|
195
|
+
*/
|
|
196
|
+
it('should handle 2000 level deep hierarchy without issues', () => {
|
|
197
|
+
const DEPTH = 2000;
|
|
198
|
+
const root = new SimpleWorkflow('Root');
|
|
199
|
+
let current: any = root;
|
|
200
|
+
|
|
201
|
+
// Build deep hierarchy
|
|
202
|
+
for (let i = 0; i < DEPTH; i++) {
|
|
203
|
+
current = new SimpleWorkflow(`Child-${i}`, current);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Both operations should work without stack overflow
|
|
207
|
+
const foundRoot = (current as any).getRoot();
|
|
208
|
+
expect(foundRoot.id).toBe(root.id);
|
|
209
|
+
|
|
210
|
+
const isDescendant = (current as any).isDescendantOf(root);
|
|
211
|
+
expect(isDescendant).toBe(true);
|
|
212
|
+
});
|
|
213
|
+
});
|
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* End-to-End PRD Validation Tests
|
|
3
|
+
* Creative testing of actual implementation against PRD requirements
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, expect } from 'vitest';
|
|
7
|
+
import { Workflow, Step, Task, ObservedState } from '../../index.js';
|
|
8
|
+
import { WorkflowTreeDebugger } from '../../debugger/tree-debugger.js';
|
|
9
|
+
import type { WorkflowEvent, WorkflowError } from '../../types/index.js';
|
|
10
|
+
|
|
11
|
+
describe('End-to-End PRD Validation', () => {
|
|
12
|
+
describe('PRD Example from Section 13', () => {
|
|
13
|
+
// PRD provides an example TDD workflow - let's test it exactly
|
|
14
|
+
it('should support the exact TDD workflow example from PRD', async () => {
|
|
15
|
+
class TestCycleWorkflow extends Workflow {
|
|
16
|
+
@ObservedState()
|
|
17
|
+
currentTest!: string;
|
|
18
|
+
|
|
19
|
+
@Step({ snapshotState: true })
|
|
20
|
+
async generateTest() {
|
|
21
|
+
this.currentTest = 'test-example';
|
|
22
|
+
return 'generated';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@Step()
|
|
26
|
+
async runTest() {
|
|
27
|
+
this.logger.info('Running test');
|
|
28
|
+
return 'passed';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@Step()
|
|
32
|
+
async updateImplementation() {
|
|
33
|
+
return 'updated';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async run() {
|
|
37
|
+
await this.generateTest();
|
|
38
|
+
await this.runTest();
|
|
39
|
+
await this.updateImplementation();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
class TDDOrchestrator extends Workflow {
|
|
44
|
+
@Step({ logStart: true })
|
|
45
|
+
async setupEnvironment() {
|
|
46
|
+
this.logger.info('Environment setup complete');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@Task()
|
|
50
|
+
async runCycle() {
|
|
51
|
+
return new TestCycleWorkflow('Cycle', this);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async run() {
|
|
55
|
+
await this.setupEnvironment();
|
|
56
|
+
await this.runCycle();
|
|
57
|
+
await this.children[0].run();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const workflow = new TDDOrchestrator();
|
|
62
|
+
await workflow.run();
|
|
63
|
+
|
|
64
|
+
// Verify hierarchy
|
|
65
|
+
expect(workflow.children.length).toBe(1);
|
|
66
|
+
expect(workflow.children[0].node.name).toBe('Cycle');
|
|
67
|
+
|
|
68
|
+
// Verify state was captured
|
|
69
|
+
expect(workflow.children[0].node.stateSnapshot).not.toBeNull();
|
|
70
|
+
expect(workflow.children[0].node.stateSnapshot?.currentTest).toBe('test-example');
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe('PRD: Restart Semantics - Error Analysis', () => {
|
|
75
|
+
it('should capture error state for parent restart decision', async () => {
|
|
76
|
+
let capturedError: WorkflowError | undefined;
|
|
77
|
+
|
|
78
|
+
class ChildWorkflow extends Workflow {
|
|
79
|
+
@ObservedState()
|
|
80
|
+
attemptCount = 0;
|
|
81
|
+
|
|
82
|
+
@Step()
|
|
83
|
+
async failingOperation() {
|
|
84
|
+
this.attemptCount++;
|
|
85
|
+
this.logger.info(`Attempt ${this.attemptCount}`);
|
|
86
|
+
if (this.attemptCount < 3) {
|
|
87
|
+
throw new Error('Not ready yet');
|
|
88
|
+
}
|
|
89
|
+
return 'success';
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async run() {
|
|
93
|
+
return this.failingOperation();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
class ParentWorkflow extends Workflow {
|
|
98
|
+
@Task()
|
|
99
|
+
async spawnChild() {
|
|
100
|
+
return new ChildWorkflow('Child', this);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async run() {
|
|
104
|
+
await this.spawnChild();
|
|
105
|
+
|
|
106
|
+
// Subscribe to errors for restart logic
|
|
107
|
+
this.addObserver({
|
|
108
|
+
onLog: () => {},
|
|
109
|
+
onEvent: (e) => {
|
|
110
|
+
if (e.type === 'error') {
|
|
111
|
+
capturedError = e.error;
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
onStateUpdated: () => {},
|
|
115
|
+
onTreeChanged: () => {},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
await this.children[0].run();
|
|
120
|
+
} catch (err) {
|
|
121
|
+
// Analyze error and state for restart decision
|
|
122
|
+
expect(capturedError).toBeDefined();
|
|
123
|
+
expect(capturedError!.state.attemptCount).toBeGreaterThan(0);
|
|
124
|
+
expect(capturedError!.logs.length).toBeGreaterThan(0);
|
|
125
|
+
|
|
126
|
+
// Could decide to retry based on capturedError.state
|
|
127
|
+
// For this test, we just verified the error has all needed info
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const workflow = new ParentWorkflow();
|
|
133
|
+
await workflow.run();
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
describe('PRD: @Step trackTiming default behavior', () => {
|
|
138
|
+
it('should track timing by default when not specified (true by default)', async () => {
|
|
139
|
+
const events: WorkflowEvent[] = [];
|
|
140
|
+
|
|
141
|
+
class TestWorkflow extends Workflow {
|
|
142
|
+
@Step() // No options - should default to trackTiming: true
|
|
143
|
+
async testStep() {
|
|
144
|
+
return 'done';
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async run() {
|
|
148
|
+
return this.testStep();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const workflow = new TestWorkflow();
|
|
153
|
+
workflow.addObserver({
|
|
154
|
+
onLog: () => {},
|
|
155
|
+
onEvent: (e) => events.push(e),
|
|
156
|
+
onStateUpdated: () => {},
|
|
157
|
+
onTreeChanged: () => {},
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
await workflow.run();
|
|
161
|
+
|
|
162
|
+
const stepEndEvent = events.find(e => e.type === 'stepEnd');
|
|
163
|
+
expect(stepEndEvent).toBeDefined();
|
|
164
|
+
if (stepEndEvent?.type === 'stepEnd') {
|
|
165
|
+
expect(typeof stepEndEvent.duration).toBe('number');
|
|
166
|
+
expect(stepEndEvent.duration).toBeGreaterThanOrEqual(0);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe('PRD: Tree Debugger API Completeness', () => {
|
|
172
|
+
it('should implement all required methods from WorkflowTreeDebugger', async () => {
|
|
173
|
+
class TestWorkflow extends Workflow {
|
|
174
|
+
async run() {
|
|
175
|
+
this.logger.info('Test log');
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const workflow = new TestWorkflow();
|
|
180
|
+
const treeDebugger = new WorkflowTreeDebugger(workflow);
|
|
181
|
+
|
|
182
|
+
// Test getTree()
|
|
183
|
+
const tree = treeDebugger.getTree();
|
|
184
|
+
expect(tree).toBeDefined();
|
|
185
|
+
expect(tree.id).toBe(workflow.id);
|
|
186
|
+
|
|
187
|
+
// Test getNode()
|
|
188
|
+
const node = treeDebugger.getNode(workflow.id);
|
|
189
|
+
expect(node).toBeDefined();
|
|
190
|
+
expect(node!.id).toBe(workflow.id);
|
|
191
|
+
|
|
192
|
+
// Test events observable
|
|
193
|
+
expect(treeDebugger.events).toBeDefined();
|
|
194
|
+
expect(typeof treeDebugger.events.subscribe).toBe('function');
|
|
195
|
+
|
|
196
|
+
// Test toTreeString()
|
|
197
|
+
const treeString = treeDebugger.toTreeString();
|
|
198
|
+
expect(typeof treeString).toBe('string');
|
|
199
|
+
expect(treeString.length).toBeGreaterThan(0);
|
|
200
|
+
|
|
201
|
+
// Test toLogString()
|
|
202
|
+
await workflow.run();
|
|
203
|
+
const logString = treeDebugger.toLogString();
|
|
204
|
+
expect(typeof logString).toBe('string');
|
|
205
|
+
expect(logString).toContain('Test log');
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
describe('PRD: WorkflowError Complete Structure', () => {
|
|
210
|
+
it('should include all required fields per PRD Section 5.1', async () => {
|
|
211
|
+
class TestWorkflow extends Workflow {
|
|
212
|
+
@ObservedState()
|
|
213
|
+
contextData = 'important';
|
|
214
|
+
|
|
215
|
+
@Step()
|
|
216
|
+
async failingStep() {
|
|
217
|
+
this.logger.info('About to fail');
|
|
218
|
+
throw new Error('Intentional failure');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
async run() {
|
|
222
|
+
try {
|
|
223
|
+
await this.failingStep();
|
|
224
|
+
} catch (err) {
|
|
225
|
+
const wfError = err as WorkflowError;
|
|
226
|
+
|
|
227
|
+
// Verify all required fields from PRD Section 5.1
|
|
228
|
+
expect(wfError.message).toBe('Intentional failure');
|
|
229
|
+
expect(wfError.original).toBeDefined();
|
|
230
|
+
expect(wfError.workflowId).toBeDefined();
|
|
231
|
+
expect(wfError.stack).toBeDefined();
|
|
232
|
+
expect(wfError.state).toBeDefined();
|
|
233
|
+
expect(wfError.logs).toBeDefined();
|
|
234
|
+
expect(Array.isArray(wfError.logs)).toBe(true);
|
|
235
|
+
expect(wfError.state.contextData).toBe('important');
|
|
236
|
+
expect(wfError.logs.some(l => l.message.includes('About to fail'))).toBe(true);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const workflow = new TestWorkflow();
|
|
242
|
+
await workflow.run();
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
describe('PRD: Root-Only Observer Restriction', () => {
|
|
247
|
+
it('should only allow observers on root workflow', async () => {
|
|
248
|
+
class ChildWorkflow extends Workflow {
|
|
249
|
+
async run() {
|
|
250
|
+
return 'done';
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
class ParentWorkflow extends Workflow {
|
|
255
|
+
async run() {
|
|
256
|
+
const child = new ChildWorkflow('Child', this);
|
|
257
|
+
|
|
258
|
+
// Should throw when trying to add observer to non-root
|
|
259
|
+
expect(() => {
|
|
260
|
+
child.addObserver({
|
|
261
|
+
onLog: () => {},
|
|
262
|
+
onEvent: () => {},
|
|
263
|
+
onStateUpdated: () => {},
|
|
264
|
+
onTreeChanged: () => {},
|
|
265
|
+
});
|
|
266
|
+
}).toThrow('Observers can only be added to root workflows');
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const workflow = new ParentWorkflow();
|
|
271
|
+
await workflow.run();
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
describe('PRD: Step Snapshot Timing', () => {
|
|
276
|
+
it('should snapshot state AFTER step completion', async () => {
|
|
277
|
+
class TestWorkflow extends Workflow {
|
|
278
|
+
@ObservedState()
|
|
279
|
+
value = 'before';
|
|
280
|
+
|
|
281
|
+
@Step({ snapshotState: true })
|
|
282
|
+
async changeAndSnapshot() {
|
|
283
|
+
this.value = 'after';
|
|
284
|
+
// Snapshot should capture 'after' since it's after step completion
|
|
285
|
+
return 'done';
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
async run() {
|
|
289
|
+
await this.changeAndSnapshot();
|
|
290
|
+
return this.node.stateSnapshot;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const workflow = new TestWorkflow();
|
|
295
|
+
const snapshot = await workflow.run();
|
|
296
|
+
|
|
297
|
+
expect(snapshot?.value).toBe('after');
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
describe('Creative: Real-world TDD Workflow Scenario', () => {
|
|
302
|
+
it('should handle realistic test-driven development cycle', async () => {
|
|
303
|
+
const testResults: string[] = [];
|
|
304
|
+
|
|
305
|
+
class TestWorkflow extends Workflow {
|
|
306
|
+
@ObservedState()
|
|
307
|
+
testName = '';
|
|
308
|
+
|
|
309
|
+
@ObservedState()
|
|
310
|
+
passed = false;
|
|
311
|
+
|
|
312
|
+
@Step({ logStart: true, logFinish: true })
|
|
313
|
+
async writeTest(testName: string) {
|
|
314
|
+
this.testName = testName;
|
|
315
|
+
this.logger.info(`Writing test: ${testName}`);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
@Step({ trackTiming: true })
|
|
319
|
+
async runTest() {
|
|
320
|
+
this.logger.info('Running test...');
|
|
321
|
+
// Simulate test failure
|
|
322
|
+
this.passed = false;
|
|
323
|
+
throw new Error('Test failed: Implementation missing');
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
@Step()
|
|
327
|
+
async writeCode() {
|
|
328
|
+
this.logger.info('Writing implementation...');
|
|
329
|
+
this.passed = true;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
async run(testName: string) {
|
|
333
|
+
await this.writeTest(testName);
|
|
334
|
+
try {
|
|
335
|
+
await this.runTest();
|
|
336
|
+
} catch (err) {
|
|
337
|
+
// Test failed - write code
|
|
338
|
+
await this.writeCode();
|
|
339
|
+
// Retry test
|
|
340
|
+
this.passed = true;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
class Orchestrator extends Workflow {
|
|
346
|
+
@Task()
|
|
347
|
+
async runTestCycle(testName: string) {
|
|
348
|
+
return new TestWorkflow('TestCycle', this);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
async run() {
|
|
352
|
+
const testNames = ['shouldAdd', 'shouldSubtract', 'shouldMultiply'];
|
|
353
|
+
|
|
354
|
+
for (const name of testNames) {
|
|
355
|
+
await this.runTestCycle(name);
|
|
356
|
+
const testWf = this.children[this.children.length - 1];
|
|
357
|
+
await testWf.run(name);
|
|
358
|
+
testResults.push(`${name}:${testWf.node.status}`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const workflow = new Orchestrator();
|
|
364
|
+
await workflow.run();
|
|
365
|
+
|
|
366
|
+
expect(workflow.children.length).toBe(3);
|
|
367
|
+
expect(testResults.length).toBe(3);
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
describe('Creative: Nested Error Propagation', () => {
|
|
372
|
+
it('should properly handle errors at multiple hierarchy levels', async () => {
|
|
373
|
+
const errorsAtLevel: { level: string; error: string }[] = [];
|
|
374
|
+
|
|
375
|
+
class Level3Workflow extends Workflow {
|
|
376
|
+
@ObservedState()
|
|
377
|
+
level = 3;
|
|
378
|
+
|
|
379
|
+
@Step()
|
|
380
|
+
async doWork() {
|
|
381
|
+
throw new Error('Level 3 error');
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
async run() {
|
|
385
|
+
return this.doWork();
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
class Level2Workflow extends Workflow {
|
|
390
|
+
@ObservedState()
|
|
391
|
+
level = 2;
|
|
392
|
+
|
|
393
|
+
@Task()
|
|
394
|
+
async spawnLevel3() {
|
|
395
|
+
return new Level3Workflow('Level3', this);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
async run() {
|
|
399
|
+
await this.spawnLevel3();
|
|
400
|
+
try {
|
|
401
|
+
await this.children[0].run();
|
|
402
|
+
} catch (err) {
|
|
403
|
+
errorsAtLevel.push({ level: '2', error: (err as any).message });
|
|
404
|
+
throw new Error('Level 2 wrapper error');
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
class Level1Workflow extends Workflow {
|
|
410
|
+
@ObservedState()
|
|
411
|
+
level = 1;
|
|
412
|
+
|
|
413
|
+
@Task()
|
|
414
|
+
async spawnLevel2() {
|
|
415
|
+
return new Level2Workflow('Level2', this);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
async run() {
|
|
419
|
+
await this.spawnLevel2();
|
|
420
|
+
try {
|
|
421
|
+
await this.children[0].run();
|
|
422
|
+
} catch (err) {
|
|
423
|
+
errorsAtLevel.push({ level: '1', error: (err as any).message });
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const workflow = new Level1Workflow();
|
|
429
|
+
|
|
430
|
+
// Add observer to capture all errors
|
|
431
|
+
workflow.addObserver({
|
|
432
|
+
onLog: () => {},
|
|
433
|
+
onEvent: (e) => {
|
|
434
|
+
if (e.type === 'error') {
|
|
435
|
+
errorsAtLevel.push({ level: 'observer', error: e.error.message });
|
|
436
|
+
}
|
|
437
|
+
},
|
|
438
|
+
onStateUpdated: () => {},
|
|
439
|
+
onTreeChanged: () => {},
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
await workflow.run();
|
|
443
|
+
|
|
444
|
+
// Should have captured errors at multiple levels
|
|
445
|
+
expect(errorsAtLevel.length).toBeGreaterThan(0);
|
|
446
|
+
});
|
|
447
|
+
});
|
|
448
|
+
});
|