groundswell 0.0.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +26 -9
- package/dist/cache/cache-key.d.ts +86 -0
- package/dist/cache/cache-key.d.ts.map +1 -0
- package/dist/cache/cache-key.js +204 -0
- package/dist/cache/cache-key.js.map +1 -0
- package/dist/cache/cache.d.ts +104 -0
- package/dist/cache/cache.d.ts.map +1 -0
- package/dist/cache/cache.js +179 -0
- package/dist/cache/cache.js.map +1 -0
- package/{src/cache/index.ts → dist/cache/index.d.ts} +1 -1
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +6 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/core/agent.d.ts +203 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +833 -0
- package/dist/core/agent.js.map +1 -0
- package/{src/core/context.ts → dist/core/context.d.ts} +16 -67
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +80 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/event-tree.d.ts +72 -0
- package/dist/core/event-tree.d.ts.map +1 -0
- package/dist/core/event-tree.js +211 -0
- package/dist/core/event-tree.js.map +1 -0
- package/{src/core/factory.ts → dist/core/factory.d.ts} +6 -27
- package/dist/core/factory.d.ts.map +1 -0
- package/dist/core/factory.js +110 -0
- package/dist/core/factory.js.map +1 -0
- package/{src/core/index.ts → dist/core/index.d.ts} +2 -10
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +9 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/logger.d.ts +50 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +91 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/mcp-handler.d.ts +127 -0
- package/dist/core/mcp-handler.d.ts.map +1 -0
- package/dist/core/mcp-handler.js +323 -0
- package/dist/core/mcp-handler.js.map +1 -0
- package/dist/core/prompt.d.ts +80 -0
- package/dist/core/prompt.d.ts.map +1 -0
- package/dist/core/prompt.js +120 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/workflow-context.d.ts +61 -0
- package/dist/core/workflow-context.d.ts.map +1 -0
- package/dist/core/workflow-context.js +358 -0
- package/dist/core/workflow-context.js.map +1 -0
- package/dist/core/workflow.d.ts +543 -0
- package/dist/core/workflow.d.ts.map +1 -0
- package/dist/core/workflow.js +986 -0
- package/dist/core/workflow.js.map +1 -0
- package/dist/debugger/event-replayer.d.ts +422 -0
- package/dist/debugger/event-replayer.d.ts.map +1 -0
- package/dist/debugger/event-replayer.js +639 -0
- package/dist/debugger/event-replayer.js.map +1 -0
- package/dist/debugger/index.d.ts +2 -0
- package/dist/debugger/index.d.ts.map +1 -0
- package/{src/debugger/index.ts → dist/debugger/index.js} +1 -0
- package/dist/debugger/index.js.map +1 -0
- package/dist/debugger/tree-debugger.d.ts +240 -0
- package/dist/debugger/tree-debugger.d.ts.map +1 -0
- package/dist/debugger/tree-debugger.js +620 -0
- package/dist/debugger/tree-debugger.js.map +1 -0
- package/dist/decorators/index.d.ts +4 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/{src/decorators/index.ts → dist/decorators/index.js} +1 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/observed-state.d.ts +32 -0
- package/dist/decorators/observed-state.d.ts.map +1 -0
- package/dist/decorators/observed-state.js +79 -0
- package/dist/decorators/observed-state.js.map +1 -0
- package/dist/decorators/step.d.ts +15 -0
- package/dist/decorators/step.d.ts.map +1 -0
- package/dist/decorators/step.js +192 -0
- package/dist/decorators/step.js.map +1 -0
- package/dist/decorators/task.d.ts +50 -0
- package/dist/decorators/task.d.ts.map +1 -0
- package/dist/decorators/task.js +118 -0
- package/dist/decorators/task.js.map +1 -0
- package/dist/examples/index.d.ts +3 -0
- package/dist/examples/index.d.ts.map +1 -0
- package/{src/examples/index.ts → dist/examples/index.js} +1 -0
- package/dist/examples/index.js.map +1 -0
- package/dist/examples/tdd-orchestrator.d.ts +15 -0
- package/dist/examples/tdd-orchestrator.d.ts.map +1 -0
- package/dist/examples/tdd-orchestrator.js +121 -0
- package/dist/examples/tdd-orchestrator.js.map +1 -0
- package/dist/examples/test-cycle-workflow.d.ts +14 -0
- package/dist/examples/test-cycle-workflow.d.ts.map +1 -0
- package/dist/examples/test-cycle-workflow.js +116 -0
- package/dist/examples/test-cycle-workflow.js.map +1 -0
- package/dist/harnesses/claude-code-harness.d.ts +391 -0
- package/dist/harnesses/claude-code-harness.d.ts.map +1 -0
- package/dist/harnesses/claude-code-harness.js +1076 -0
- package/dist/harnesses/claude-code-harness.js.map +1 -0
- package/dist/harnesses/harness-registry.d.ts +440 -0
- package/dist/harnesses/harness-registry.d.ts.map +1 -0
- package/dist/harnesses/harness-registry.js +543 -0
- package/dist/harnesses/harness-registry.js.map +1 -0
- package/dist/harnesses/index.d.ts +12 -0
- package/dist/harnesses/index.d.ts.map +1 -0
- package/dist/harnesses/index.js +11 -0
- package/dist/harnesses/index.js.map +1 -0
- package/dist/harnesses/pi-harness.d.ts +219 -0
- package/dist/harnesses/pi-harness.d.ts.map +1 -0
- package/dist/harnesses/pi-harness.js +676 -0
- package/dist/harnesses/pi-harness.js.map +1 -0
- package/dist/harnesses/pi-schema-converter.d.ts +24 -0
- package/dist/harnesses/pi-schema-converter.d.ts.map +1 -0
- package/dist/harnesses/pi-schema-converter.js +81 -0
- package/dist/harnesses/pi-schema-converter.js.map +1 -0
- package/dist/harnesses/register-defaults.d.ts +24 -0
- package/dist/harnesses/register-defaults.d.ts.map +1 -0
- package/dist/harnesses/register-defaults.js +40 -0
- package/dist/harnesses/register-defaults.js.map +1 -0
- package/dist/harnesses/session-store.d.ts +201 -0
- package/dist/harnesses/session-store.d.ts.map +1 -0
- package/dist/harnesses/session-store.js +254 -0
- package/dist/harnesses/session-store.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/reflection/index.d.ts +5 -0
- package/dist/reflection/index.d.ts.map +1 -0
- package/{src/reflection/index.ts → dist/reflection/index.js} +1 -1
- package/dist/reflection/index.js.map +1 -0
- package/dist/reflection/reflection.d.ts +84 -0
- package/dist/reflection/reflection.d.ts.map +1 -0
- package/dist/reflection/reflection.js +344 -0
- package/dist/reflection/reflection.js.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +11 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/introspection.d.ts +165 -0
- package/dist/tools/introspection.d.ts.map +1 -0
- package/dist/tools/introspection.js +324 -0
- package/dist/tools/introspection.js.map +1 -0
- package/dist/types/agent.d.ts +1317 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +423 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/decorators.d.ts +40 -0
- package/dist/types/decorators.d.ts.map +1 -0
- package/dist/types/decorators.js +2 -0
- package/dist/types/decorators.js.map +1 -0
- package/dist/types/error-strategy.d.ts +13 -0
- package/dist/types/error-strategy.d.ts.map +1 -0
- package/dist/types/error-strategy.js +2 -0
- package/dist/types/error-strategy.js.map +1 -0
- package/dist/types/error.d.ts +20 -0
- package/dist/types/error.d.ts.map +1 -0
- package/dist/types/error.js +2 -0
- package/dist/types/error.js.map +1 -0
- package/dist/types/events.d.ts +113 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +2 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/harnesses.d.ts +474 -0
- package/dist/types/harnesses.d.ts.map +1 -0
- package/dist/types/harnesses.js +2 -0
- package/dist/types/harnesses.js.map +1 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/logging.d.ts +24 -0
- package/dist/types/logging.d.ts.map +1 -0
- package/dist/types/logging.js +2 -0
- package/dist/types/logging.js.map +1 -0
- package/dist/types/observer.d.ts +18 -0
- package/dist/types/observer.d.ts.map +1 -0
- package/dist/types/observer.js +2 -0
- package/dist/types/observer.js.map +1 -0
- package/dist/types/prompt.d.ts +31 -0
- package/dist/types/prompt.d.ts.map +1 -0
- package/dist/types/prompt.js +6 -0
- package/dist/types/prompt.js.map +1 -0
- package/dist/types/providers.d.ts +691 -0
- package/dist/types/providers.d.ts.map +1 -0
- package/dist/types/providers.js +14 -0
- package/dist/types/providers.js.map +1 -0
- package/dist/types/reflection.d.ts +96 -0
- package/dist/types/reflection.d.ts.map +1 -0
- package/dist/types/reflection.js +24 -0
- package/dist/types/reflection.js.map +1 -0
- package/dist/types/restart.d.ts +132 -0
- package/dist/types/restart.d.ts.map +1 -0
- package/dist/types/restart.js +2 -0
- package/dist/types/restart.js.map +1 -0
- package/dist/types/sdk-primitives.d.ts +118 -0
- package/dist/types/sdk-primitives.d.ts.map +1 -0
- package/dist/types/sdk-primitives.js +6 -0
- package/dist/types/sdk-primitives.js.map +1 -0
- package/{src/types/snapshot.ts → dist/types/snapshot.d.ts} +5 -5
- package/dist/types/snapshot.d.ts.map +1 -0
- package/dist/types/snapshot.js +2 -0
- package/dist/types/snapshot.js.map +1 -0
- package/dist/types/streaming.d.ts +194 -0
- package/dist/types/streaming.d.ts.map +1 -0
- package/dist/types/streaming.js +67 -0
- package/dist/types/streaming.js.map +1 -0
- package/dist/types/workflow-context.d.ts +275 -0
- package/dist/types/workflow-context.d.ts.map +1 -0
- package/dist/types/workflow-context.js +8 -0
- package/dist/types/workflow-context.js.map +1 -0
- package/dist/types/workflow.d.ts +30 -0
- package/dist/types/workflow.d.ts.map +1 -0
- package/dist/types/workflow.js +2 -0
- package/dist/types/workflow.js.map +1 -0
- package/dist/utils/agent-validation.d.ts +88 -0
- package/dist/utils/agent-validation.d.ts.map +1 -0
- package/dist/utils/agent-validation.js +87 -0
- package/dist/utils/agent-validation.js.map +1 -0
- package/dist/utils/delay.d.ts +7 -0
- package/dist/utils/delay.d.ts.map +1 -0
- package/dist/utils/delay.js +9 -0
- package/dist/utils/delay.js.map +1 -0
- package/dist/utils/harness-config.d.ts +180 -0
- package/dist/utils/harness-config.d.ts.map +1 -0
- package/dist/utils/harness-config.js +311 -0
- package/dist/utils/harness-config.js.map +1 -0
- package/dist/utils/id.d.ts +6 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js +12 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/utils/index.d.ts +13 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +11 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/model-spec.d.ts +110 -0
- package/dist/utils/model-spec.d.ts.map +1 -0
- package/dist/utils/model-spec.js +149 -0
- package/dist/utils/model-spec.js.map +1 -0
- package/dist/utils/observable.d.ts +54 -0
- package/dist/utils/observable.d.ts.map +1 -0
- package/dist/utils/observable.js +82 -0
- package/dist/utils/observable.js.map +1 -0
- package/dist/utils/provider-config.d.ts +10 -0
- package/dist/utils/provider-config.d.ts.map +1 -0
- package/dist/utils/provider-config.js +10 -0
- package/dist/utils/provider-config.js.map +1 -0
- package/dist/utils/restart-analysis.d.ts +202 -0
- package/dist/utils/restart-analysis.d.ts.map +1 -0
- package/dist/utils/restart-analysis.js +426 -0
- package/dist/utils/restart-analysis.js.map +1 -0
- package/dist/utils/session-serialization.d.ts +118 -0
- package/dist/utils/session-serialization.d.ts.map +1 -0
- package/dist/utils/session-serialization.js +217 -0
- package/dist/utils/session-serialization.js.map +1 -0
- package/dist/utils/workflow-error-utils.d.ts +22 -0
- package/dist/utils/workflow-error-utils.d.ts.map +1 -0
- package/dist/utils/workflow-error-utils.js +45 -0
- package/dist/utils/workflow-error-utils.js.map +1 -0
- package/package.json +34 -5
- package/.claude/commands/subtask-planning/prp-base-create.md +0 -120
- package/.claude/commands/subtask-planning/prp-base-execute.md +0 -65
- package/.claude/commands/task-breakdown.md +0 -94
- package/.claude/settings.local.json +0 -9
- package/.claude/system_prompts/task-breakdown.md +0 -101
- package/CHANGELOG.md +0 -188
- package/PRD.md +0 -543
- package/PRPs/001-hierarchical-workflow-engine.md +0 -2438
- package/PRPs/PRDs/002-agent-prompt.md +0 -390
- package/PRPs/PRDs/003-agent-prompt.md +0 -943
- package/PRPs/PRDs/004-agent-prompt.md +0 -1136
- package/PRPs/PRDs/tasks-001.json +0 -492
- package/PRPs/README.md +0 -83
- package/PRPs/templates/prp_base.md +0 -222
- package/docs/agent.md +0 -422
- package/docs/prompt.md +0 -419
- package/docs/workflow.md +0 -600
- package/examples/README.md +0 -258
- package/examples/examples/01-basic-workflow.ts +0 -100
- package/examples/examples/02-decorator-options.ts +0 -217
- package/examples/examples/03-parent-child.ts +0 -241
- package/examples/examples/04-observers-debugger.ts +0 -340
- package/examples/examples/05-error-handling.ts +0 -387
- package/examples/examples/06-concurrent-tasks.ts +0 -352
- package/examples/examples/07-agent-loops.ts +0 -432
- package/examples/examples/08-sdk-features.ts +0 -667
- package/examples/examples/09-reflection.ts +0 -573
- package/examples/examples/10-introspection.ts +0 -550
- package/examples/examples/11-reparenting-workflows.ts +0 -269
- package/examples/index.ts +0 -147
- package/examples/utils/helpers.ts +0 -57
- package/package-lock.json +0 -2398
- package/plan/001_d3bb02af4886/TEST_RESULTS.md +0 -259
- package/plan/001_d3bb02af4886/backlog.json +0 -867
- package/plan/001_d3bb02af4886/bug_fix_tasks.json +0 -484
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S1/PRP.md +0 -488
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S2/PRP.md +0 -581
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S3/PRP.md +0 -687
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S1/PRP.md +0 -492
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/PRP.md +0 -932
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/concurrent_error_testing_patterns.md +0 -1109
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/vitest_concurrent_testing.md +0 -802
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/workflow_engine_test_references.md +0 -603
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S1/PRP.md +0 -564
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S3/PRP.md +0 -518
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S4/PRP.md +0 -1252
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/PRP.md +0 -364
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/CODEBASE_INVENTORY.md +0 -114
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/DECORATOR_DOCUMENTATION_PATTERNS.md +0 -205
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/PRD_LOCATION_ANALYSIS.md +0 -199
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/ULTRATHINK_PRP_PLAN.md +0 -134
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/PRP.md +0 -495
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/research/console_error_inventory.md +0 -435
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S2/PRP.md +0 -506
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S3/PRP.md +0 -612
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/PRP.md +0 -558
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/research/external_research.md +0 -788
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S2/PRP.md +0 -460
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S3/PRP.md +0 -454
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/PRP.md +0 -520
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/RECOMMENDATION.md +0 -417
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/external_workflow_engines_research.md +0 -760
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/security_implications_analysis.md +0 -245
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S2/PRP.md +0 -792
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/PRP.md +0 -535
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/TEST_EXECUTION_REPORT.md +0 -190
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/PRP.md +0 -654
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/TEST_FIX_REPORT.md +0 -227
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/KEY_FINDINGS.md +0 -345
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/QUICK_REFERENCE.md +0 -193
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/test_maintenance_research.md +0 -1323
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/BREAKING_CHANGES_AUDIT.md +0 -1011
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/PRP.md +0 -927
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S2/PRP.md +0 -505
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/architecture/logger_child_signature_analysis.md +0 -401
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/child_implementation_research.md +0 -142
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/test_patterns_research.md +0 -112
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/vitest_patterns_research.md +0 -159
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/PRP.md +0 -549
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/VERIFICATION_REPORT.md +0 -368
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/edge_case_analysis.md +0 -172
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/usage_inventory.md +0 -175
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S2/PRP.md +0 -696
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S4/PRP.md +0 -860
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/PRP.md +0 -1066
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01-testing-aggregated-errors.md +0 -1103
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01_typescript_error_aggregation_patterns.md +0 -789
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02-error-merge-strategy-testing-guide.md +0 -1098
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02_aggregate_error_patterns.md +0 -1037
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03-promise-allsettled-testing-patterns.md +0 -916
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03_error_merging_strategies.md +0 -1045
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/04_github_stackoverflow_examples.md +0 -890
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/05_comprehensive_summary.md +0 -822
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/INDEX.md +0 -668
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/QUICK_REFERENCE.md +0 -706
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/README.md +0 -265
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/RESEARCH_REPORT.md +0 -655
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S4/research/vitest_testing_patterns.md +0 -1103
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T3S2/PRP.md +0 -426
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/PRP.md +0 -506
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/QUICK_REFERENCE.md +0 -114
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/RESEARCH_SUMMARY.md +0 -316
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/vitest_observer_error_logging_best_practices.md +0 -754
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S3/PRP.md +0 -612
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/PRP.md +0 -719
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/README.md +0 -215
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/analysis.md +0 -765
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S3/PRP.md +0 -718
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/DECISION.md +0 -149
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/PRP.md +0 -470
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/ULTRATHINK_PLAN.md +0 -332
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/codebase_workflow_name_analysis.md +0 -167
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/external_best_practices.md +0 -265
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/validation_patterns.md +0 -273
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S1/workflow_engine_ancestry_api_research.md +0 -760
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S3-PRP.md +0 -434
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S1/PRP.md +0 -717
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/PRP.md +0 -472
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/VALIDATION_REPORT.md +0 -125
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/research/ULTRATHINK_PRP_PLAN.md +0 -301
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/error-logging-best-practices.md +0 -1170
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/research_typescript_partial_and_overloads.md +0 -940
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-quick-reference.md +0 -151
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-research.md +0 -650
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/prd_snapshot.md +0 -259
- package/plan/001_d3bb02af4886/bugfix/P1M1T1S1/PRP.md +0 -457
- package/plan/001_d3bb02af4886/bugfix/RESEARCH_SUMMARY.md +0 -346
- package/plan/001_d3bb02af4886/bugfix/architecture/codebase_structure.md +0 -311
- package/plan/001_d3bb02af4886/bugfix/architecture/concurrent_execution_best_practices.md +0 -1565
- package/plan/001_d3bb02af4886/bugfix/architecture/error_handling_patterns.md +0 -288
- package/plan/001_d3bb02af4886/bugfix/architecture/promise_all_analysis.md +0 -741
- package/plan/001_d3bb02af4886/docs/PRP/P1M1T1S4-functional-workflow-error-state-capture-test.md +0 -652
- package/plan/001_d3bb02af4886/docs/PRP/P1P2-PRP.md +0 -527
- package/plan/001_d3bb02af4886/docs/PRP/P3P4-PRP.md +0 -1388
- package/plan/001_d3bb02af4886/docs/PRP/P4P5-PRP.md +0 -1136
- package/plan/001_d3bb02af4886/docs/PRP/PRP.md +0 -527
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S1-PRP.md +0 -415
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S2-PRP.md +0 -378
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S4-PRP.md +0 -713
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M2T1S4-PRP.md +0 -370
- package/plan/001_d3bb02af4886/docs/PRP_P1M3T1S3.md +0 -499
- package/plan/001_d3bb02af4886/docs/TEST_RESULTS.md +0 -230
- package/plan/001_d3bb02af4886/docs/architecture/external_deps.md +0 -358
- package/plan/001_d3bb02af4886/docs/architecture/system_context.md +0 -242
- package/plan/001_d3bb02af4886/docs/bugfix/ANALYSIS_PRD_VS_IMPLEMENTATION.md +0 -1134
- package/plan/001_d3bb02af4886/docs/bugfix/GAP_ANALYSIS_SUMMARY.md +0 -179
- package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/PRP.md +0 -629
- package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/validation-report.md +0 -214
- package/plan/001_d3bb02af4886/docs/bugfix/PRP_P1M4T2S3.md +0 -629
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_PRP.md +0 -529
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_QUICK_REFERENCE.md +0 -142
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_README.md +0 -304
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_TEST_RESULTS.md +0 -558
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_VALIDATION_SUMMARY.md +0 -256
- package/plan/001_d3bb02af4886/docs/bugfix/system_context.md +0 -346
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/bug_analysis.md +0 -415
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/implementation_patterns.md +0 -489
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/system_context.md +0 -218
- package/plan/001_d3bb02af4886/docs/bugfix_INITIATION_SUMMARY.md +0 -380
- package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_PATTERNS.md +0 -1923
- package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_QUICK_REF.md +0 -319
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/codebase-context.md +0 -115
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/cycle-detection-algorithms.md +0 -134
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/test-patterns.md +0 -153
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/workflow-class.md +0 -132
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_BEST_PRACTICES.md +0 -716
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_QUICK_REF.md +0 -186
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/GROUNDSWELL_DECORATOR_EXAMPLES.md +0 -604
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/INDEX.md +0 -213
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/codebase_structure.md +0 -30
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/existing_test_pattern.md +0 -56
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/getRootObservers_implementation.md +0 -53
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/test_conventions.md +0 -49
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/PRP.md +0 -958
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/QUICK_REFERENCE.md +0 -339
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/README.md +0 -305
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/SUMMARY.md +0 -433
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/bidirectional-tree-consistency-testing.md +0 -1574
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/test-pattern-examples.md +0 -1014
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_BEST_PRACTICES.md +0 -1929
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_CODE_PATTERNS.md +0 -857
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_INTEGRATION_GUIDE.md +0 -738
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_RESEARCH_INDEX.md +0 -424
- package/plan/001_d3bb02af4886/docs/research/P1P2/REFLECTION_INDEX.md +0 -291
- package/plan/001_d3bb02af4886/docs/research/P1P2/REFLECTION_RESEARCH_REPORT.md +0 -1342
- package/plan/001_d3bb02af4886/docs/research/P1P2/RESEARCH_SUMMARY.md +0 -342
- package/plan/001_d3bb02af4886/docs/research/P1P2/anthropic-sdk.md +0 -174
- package/plan/001_d3bb02af4886/docs/research/P1P2/async-local-storage.md +0 -200
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-code-patterns.md +0 -1205
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-decision-matrix.md +0 -421
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-implementation-guide.md +0 -1341
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-integration-guide.md +0 -834
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-patterns.md +0 -1468
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-quick-reference.md +0 -558
- package/plan/001_d3bb02af4886/docs/research/P1P2/zod-schema.md +0 -152
- package/plan/001_d3bb02af4886/docs/research/P3P4/caching-lru.md +0 -116
- package/plan/001_d3bb02af4886/docs/research/P3P4/introspection-tools.md +0 -177
- package/plan/001_d3bb02af4886/docs/research/P3P4/reflection-patterns.md +0 -117
- package/plan/001_d3bb02af4886/docs/research/P4P5/RESEARCH_SUMMARY.md +0 -151
- package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_QUICK_REF.md +0 -376
- package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_RESEARCH.md +0 -1507
- package/plan/001_d3bb02af4886/docs/research/bugfix_typescript_patterns.md +0 -949
- package/plan/001_d3bb02af4886/docs/research/error-testing-research.md +0 -619
- package/plan/001_d3bb02af4886/docs/research/error_handling_patterns.md +0 -723
- package/plan/001_d3bb02af4886/docs/research/general/INTROSPECTION_RESEARCH_SUMMARY.md +0 -378
- package/plan/001_d3bb02af4886/docs/research/general/README-INTROSPECTION.md +0 -352
- package/plan/001_d3bb02af4886/docs/research/general/agent-introspection-patterns.md +0 -1085
- package/plan/001_d3bb02af4886/docs/research/general/introspection-security-guide.md +0 -984
- package/plan/001_d3bb02af4886/docs/research/general/introspection-tool-examples.md +0 -875
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/PRP_TEMPLATE.md +0 -460
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/QUICK_REFERENCE.md +0 -324
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/README.md +0 -175
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/RESEARCH_REPORT.md +0 -499
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/SUMMARY.md +0 -163
- package/plan/001_d3bb02af4886/prd_snapshot.md +0 -543
- package/plan/bugfix/BUG_FIX_SUMMARY.md +0 -961
- package/scripts/generate-llms-full.ts +0 -206
- package/src/__tests__/adversarial/attachChild-performance.test.ts +0 -216
- package/src/__tests__/adversarial/circular-reference.test.ts +0 -101
- package/src/__tests__/adversarial/complex-circular-reference.test.ts +0 -139
- package/src/__tests__/adversarial/concurrent-task-failures.test.ts +0 -571
- package/src/__tests__/adversarial/deep-analysis.test.ts +0 -729
- package/src/__tests__/adversarial/deep-hierarchy-stress.test.ts +0 -213
- package/src/__tests__/adversarial/e2e-prd-validation.test.ts +0 -448
- package/src/__tests__/adversarial/edge-case.test.ts +0 -703
- package/src/__tests__/adversarial/error-merge-strategy.test.ts +0 -760
- package/src/__tests__/adversarial/incremental-performance.test.ts +0 -140
- package/src/__tests__/adversarial/node-map-update-benchmarks.test.ts +0 -457
- package/src/__tests__/adversarial/observer-propagation.test.ts +0 -487
- package/src/__tests__/adversarial/parent-validation.test.ts +0 -143
- package/src/__tests__/adversarial/prd-12-2-compliance.test.ts +0 -611
- package/src/__tests__/adversarial/prd-compliance.test.ts +0 -731
- package/src/__tests__/compatibility/backward-compatibility.test.ts +0 -1572
- package/src/__tests__/helpers/index.ts +0 -18
- package/src/__tests__/helpers/tree-verification.ts +0 -257
- package/src/__tests__/integration/agent-workflow.test.ts +0 -256
- package/src/__tests__/integration/bidirectional-consistency.test.ts +0 -847
- package/src/__tests__/integration/observer-logging.test.ts +0 -643
- package/src/__tests__/integration/tree-mirroring.test.ts +0 -151
- package/src/__tests__/integration/workflow-reparenting.test.ts +0 -303
- package/src/__tests__/unit/agent.test.ts +0 -169
- package/src/__tests__/unit/cache-key.test.ts +0 -182
- package/src/__tests__/unit/cache.test.ts +0 -172
- package/src/__tests__/unit/context.test.ts +0 -217
- package/src/__tests__/unit/decorators.test.ts +0 -100
- package/src/__tests__/unit/introspection-tools.test.ts +0 -277
- package/src/__tests__/unit/logger.test.ts +0 -293
- package/src/__tests__/unit/observable.test.ts +0 -321
- package/src/__tests__/unit/prompt.test.ts +0 -135
- package/src/__tests__/unit/reflection.test.ts +0 -210
- package/src/__tests__/unit/tree-debugger-incremental.test.ts +0 -170
- package/src/__tests__/unit/tree-debugger.test.ts +0 -85
- package/src/__tests__/unit/utils/workflow-error-utils.test.ts +0 -209
- package/src/__tests__/unit/workflow-detachChild.test.ts +0 -100
- package/src/__tests__/unit/workflow-emitEvent-childDetached.test.ts +0 -153
- package/src/__tests__/unit/workflow-isDescendantOf.test.ts +0 -180
- package/src/__tests__/unit/workflow.test.ts +0 -357
- package/src/cache/cache-key.ts +0 -244
- package/src/cache/cache.ts +0 -236
- package/src/core/agent.ts +0 -593
- package/src/core/event-tree.ts +0 -260
- package/src/core/logger.ts +0 -112
- package/src/core/mcp-handler.ts +0 -184
- package/src/core/prompt.ts +0 -150
- package/src/core/workflow-context.ts +0 -351
- package/src/core/workflow.ts +0 -540
- package/src/debugger/tree-debugger.ts +0 -255
- package/src/decorators/observed-state.ts +0 -95
- package/src/decorators/step.ts +0 -139
- package/src/decorators/task.ts +0 -159
- package/src/examples/tdd-orchestrator.ts +0 -65
- package/src/examples/test-cycle-workflow.ts +0 -64
- package/src/index.ts +0 -142
- package/src/reflection/reflection.ts +0 -407
- package/src/tools/index.ts +0 -36
- package/src/tools/introspection.ts +0 -464
- package/src/types/agent.ts +0 -90
- package/src/types/decorators.ts +0 -32
- package/src/types/error-strategy.ts +0 -13
- package/src/types/error.ts +0 -20
- package/src/types/events.ts +0 -75
- package/src/types/index.ts +0 -55
- package/src/types/logging.ts +0 -24
- package/src/types/observer.ts +0 -18
- package/src/types/prompt.ts +0 -40
- package/src/types/reflection.ts +0 -117
- package/src/types/sdk-primitives.ts +0 -128
- package/src/types/workflow-context.ts +0 -163
- package/src/types/workflow.ts +0 -37
- package/src/utils/id.ts +0 -11
- package/src/utils/index.ts +0 -4
- package/src/utils/observable.ts +0 -106
- package/src/utils/workflow-error-utils.ts +0 -56
- package/tsconfig.json +0 -22
- package/vitest.config.ts +0 -16
|
@@ -1,760 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ErrorMergeStrategy Functionality Test Suite
|
|
3
|
-
*
|
|
4
|
-
* Tests the ErrorMergeStrategy feature for concurrent task error aggregation.
|
|
5
|
-
*
|
|
6
|
-
* Validates:
|
|
7
|
-
* - Default behavior (disabled) - first error wins
|
|
8
|
-
* - Enabled with default merge - uses mergeWorkflowErrors
|
|
9
|
-
* - Enabled with custom combine - user-provided merger
|
|
10
|
-
* - Edge cases - single failure, all failing, mixed scenarios
|
|
11
|
-
* - Event emission - individual and merged error events
|
|
12
|
-
* - Completion verification - all workflows complete
|
|
13
|
-
*
|
|
14
|
-
* Related:
|
|
15
|
-
* - P1.M2.T2.S2: Error aggregation logic implementation
|
|
16
|
-
* - P1.M2.T2.S3: Default error merger utility
|
|
17
|
-
* - Bug: 001_e8e04329daf3 - Concurrent task error handling
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
21
|
-
import { Workflow, Task, Step } from '../../index.js';
|
|
22
|
-
import type { WorkflowEvent, WorkflowError } from '../../types/index.js';
|
|
23
|
-
|
|
24
|
-
describe('@Task decorator ErrorMergeStrategy', () => {
|
|
25
|
-
/**
|
|
26
|
-
* Helper to create a child workflow that may fail
|
|
27
|
-
* Pattern from: src/__tests__/adversarial/concurrent-task-failures.test.ts (lines 30-52)
|
|
28
|
-
*/
|
|
29
|
-
function createChildWorkflow(
|
|
30
|
-
parent: Workflow,
|
|
31
|
-
name: string,
|
|
32
|
-
shouldFail: boolean = false
|
|
33
|
-
): Workflow {
|
|
34
|
-
return new (class extends Workflow {
|
|
35
|
-
constructor(n: string, p: Workflow) {
|
|
36
|
-
super(n, p);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
@Step()
|
|
40
|
-
async executeStep() {
|
|
41
|
-
if (shouldFail) {
|
|
42
|
-
throw new Error(`${name} failed`);
|
|
43
|
-
}
|
|
44
|
-
return `${name} succeeded`;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async run() {
|
|
48
|
-
return this.executeStep();
|
|
49
|
-
}
|
|
50
|
-
})(name, parent);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Helper to setup event observer for event collection
|
|
55
|
-
* Pattern from: src/__tests__/adversarial/concurrent-task-failures.test.ts (lines 58-67)
|
|
56
|
-
*/
|
|
57
|
-
function setupEventObserver(workflow: Workflow): WorkflowEvent[] {
|
|
58
|
-
const events: WorkflowEvent[] = [];
|
|
59
|
-
workflow.addObserver({
|
|
60
|
-
onLog: () => {},
|
|
61
|
-
onEvent: (e) => events.push(e),
|
|
62
|
-
onStateUpdated: () => {},
|
|
63
|
-
onTreeChanged: () => {},
|
|
64
|
-
});
|
|
65
|
-
return events;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Helper to create a mock WorkflowError for custom combine() tests
|
|
70
|
-
* Pattern from: src/__tests__/unit/utils/workflow-error-utils.test.ts (lines 7-25)
|
|
71
|
-
*/
|
|
72
|
-
function createMockWorkflowError(overrides?: Partial<WorkflowError>): WorkflowError {
|
|
73
|
-
return {
|
|
74
|
-
message: 'Test error',
|
|
75
|
-
original: new Error('Original error'),
|
|
76
|
-
workflowId: 'wf-test-123',
|
|
77
|
-
stack: 'Error: Test error\n at test.ts:10:15',
|
|
78
|
-
state: { key: 'value' },
|
|
79
|
-
logs: [
|
|
80
|
-
{
|
|
81
|
-
id: 'log-1',
|
|
82
|
-
workflowId: 'wf-test-123',
|
|
83
|
-
timestamp: Date.now(),
|
|
84
|
-
level: 'error',
|
|
85
|
-
message: 'Test log message',
|
|
86
|
-
},
|
|
87
|
-
],
|
|
88
|
-
...overrides,
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
describe('Default behavior (errorMergeStrategy disabled)', () => {
|
|
93
|
-
it('should throw first error when errorMergeStrategy not provided', async () => {
|
|
94
|
-
// ARRANGE: Create parent with concurrent tasks, no error merge strategy
|
|
95
|
-
class ParentWorkflow extends Workflow {
|
|
96
|
-
@Task({ concurrent: true }) // CRITICAL: concurrent=true required
|
|
97
|
-
async spawnChildren() {
|
|
98
|
-
return [
|
|
99
|
-
createChildWorkflow(this, 'Child-0', false),
|
|
100
|
-
createChildWorkflow(this, 'Child-1', true), // Will fail
|
|
101
|
-
createChildWorkflow(this, 'Child-2', false),
|
|
102
|
-
];
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async run() {
|
|
106
|
-
try {
|
|
107
|
-
await this.spawnChildren();
|
|
108
|
-
} catch (err) {
|
|
109
|
-
// Expected - capture error for validation
|
|
110
|
-
return err;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const parent = new ParentWorkflow('Parent');
|
|
116
|
-
const events = setupEventObserver(parent);
|
|
117
|
-
|
|
118
|
-
// ACT: Run parent workflow
|
|
119
|
-
const thrownError = await parent.run();
|
|
120
|
-
|
|
121
|
-
// ASSERT: All children completed (Promise.allSettled behavior)
|
|
122
|
-
expect(parent.children.length).toBe(3);
|
|
123
|
-
|
|
124
|
-
// ASSERT: Error was thrown (first error wins)
|
|
125
|
-
expect(thrownError).toBeDefined();
|
|
126
|
-
expect((thrownError as WorkflowError).message).toContain('Child-1 failed');
|
|
127
|
-
|
|
128
|
-
// ASSERT: No additional error event from @Task (only individual workflow errors)
|
|
129
|
-
const errorEvents = events.filter((e) => e.type === 'error');
|
|
130
|
-
expect(errorEvents.length).toBe(1); // Only Child-1's error event
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('should throw first error when errorMergeStrategy.enabled=false', async () => {
|
|
134
|
-
// ARRANGE: Create parent with explicit enabled=false
|
|
135
|
-
class ParentWorkflow extends Workflow {
|
|
136
|
-
@Task({
|
|
137
|
-
concurrent: true,
|
|
138
|
-
errorMergeStrategy: { enabled: false }, // Explicitly disabled
|
|
139
|
-
})
|
|
140
|
-
async spawnChildren() {
|
|
141
|
-
return [
|
|
142
|
-
createChildWorkflow(this, 'Alpha', false),
|
|
143
|
-
createChildWorkflow(this, 'Beta', true),
|
|
144
|
-
createChildWorkflow(this, 'Gamma', true),
|
|
145
|
-
];
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
async run() {
|
|
149
|
-
try {
|
|
150
|
-
await this.spawnChildren();
|
|
151
|
-
} catch (err) {
|
|
152
|
-
return err;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const parent = new ParentWorkflow('Parent');
|
|
158
|
-
const events = setupEventObserver(parent);
|
|
159
|
-
const thrownError = await parent.run();
|
|
160
|
-
|
|
161
|
-
// ASSERT: All children completed
|
|
162
|
-
expect(parent.children.length).toBe(3);
|
|
163
|
-
|
|
164
|
-
// ASSERT: First error thrown (not aggregated)
|
|
165
|
-
expect(thrownError).toBeDefined();
|
|
166
|
-
const errorMsg = (thrownError as WorkflowError).message;
|
|
167
|
-
expect(errorMsg).toMatch(/Alpha failed|Beta failed|Gamma failed/);
|
|
168
|
-
|
|
169
|
-
// ASSERT: Only individual error events (no merge event)
|
|
170
|
-
const errorEvents = events.filter((e) => e.type === 'error');
|
|
171
|
-
expect(errorEvents.length).toBe(2); // Beta and Gamma errors only
|
|
172
|
-
|
|
173
|
-
// ASSERT: Error message does not contain aggregated format
|
|
174
|
-
expect(errorMsg).not.toContain('concurrent child workflows failed');
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
describe('Enabled with default error merge', () => {
|
|
179
|
-
it('should merge all errors when errorMergeStrategy.enabled=true', async () => {
|
|
180
|
-
// ARRANGE: Create parent with error merge enabled
|
|
181
|
-
class ParentWorkflow extends Workflow {
|
|
182
|
-
@Task({
|
|
183
|
-
concurrent: true,
|
|
184
|
-
errorMergeStrategy: { enabled: true }, // No combine() - use default
|
|
185
|
-
})
|
|
186
|
-
async spawnChildren() {
|
|
187
|
-
return [
|
|
188
|
-
createChildWorkflow(this, 'Alpha', false),
|
|
189
|
-
createChildWorkflow(this, 'Beta', true), // Will fail
|
|
190
|
-
createChildWorkflow(this, 'Gamma', false),
|
|
191
|
-
createChildWorkflow(this, 'Delta', true), // Will fail
|
|
192
|
-
createChildWorkflow(this, 'Epsilon', false),
|
|
193
|
-
];
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
async run() {
|
|
197
|
-
try {
|
|
198
|
-
await this.spawnChildren();
|
|
199
|
-
} catch (err) {
|
|
200
|
-
return err;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
const parent = new ParentWorkflow('Parent');
|
|
206
|
-
const events = setupEventObserver(parent);
|
|
207
|
-
|
|
208
|
-
// ACT
|
|
209
|
-
const thrownError = await parent.run();
|
|
210
|
-
|
|
211
|
-
// ASSERT: All children completed
|
|
212
|
-
expect(parent.children.length).toBe(5);
|
|
213
|
-
|
|
214
|
-
// ASSERT: Merged error thrown
|
|
215
|
-
expect(thrownError).toBeDefined();
|
|
216
|
-
const error = thrownError as WorkflowError;
|
|
217
|
-
|
|
218
|
-
// ASSERT: Message includes count and task name
|
|
219
|
-
expect(error.message).toBe("2 of 5 concurrent child workflows failed in task 'spawnChildren'");
|
|
220
|
-
|
|
221
|
-
// ASSERT: Metadata in original field
|
|
222
|
-
const metadata = error.original as {
|
|
223
|
-
name: string;
|
|
224
|
-
message: string;
|
|
225
|
-
errors: WorkflowError[];
|
|
226
|
-
totalChildren: number;
|
|
227
|
-
failedChildren: number;
|
|
228
|
-
failedWorkflowIds: string[];
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
expect(metadata.name).toBe('WorkflowAggregateError');
|
|
232
|
-
expect(metadata.totalChildren).toBe(5);
|
|
233
|
-
expect(metadata.failedChildren).toBe(2);
|
|
234
|
-
expect(metadata.failedWorkflowIds).toHaveLength(2);
|
|
235
|
-
expect(metadata.errors).toHaveLength(2);
|
|
236
|
-
|
|
237
|
-
// ASSERT: Logs aggregated from all errors (empty array if child workflows don't log)
|
|
238
|
-
expect(error.logs).toBeDefined();
|
|
239
|
-
expect(Array.isArray(error.logs)).toBe(true);
|
|
240
|
-
// Note: Logs are empty here because createChildWorkflow doesn't log
|
|
241
|
-
// The "should aggregate all logs from all failed workflows" test specifically tests log aggregation
|
|
242
|
-
|
|
243
|
-
// ASSERT: Error event emitted with merged error
|
|
244
|
-
const errorEvents = events.filter((e) => e.type === 'error');
|
|
245
|
-
expect(errorEvents.length).toBeGreaterThanOrEqual(3); // 2 individual + 1 merged
|
|
246
|
-
|
|
247
|
-
// Find the merged error event (has different message format)
|
|
248
|
-
const mergedErrorEvent = errorEvents.find((e) => {
|
|
249
|
-
if (e.type === 'error') {
|
|
250
|
-
return e.error.message.includes('2 of 5 concurrent');
|
|
251
|
-
}
|
|
252
|
-
return false;
|
|
253
|
-
});
|
|
254
|
-
expect(mergedErrorEvent).toBeDefined();
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
it('should create aggregated error message with counts and task name', async () => {
|
|
258
|
-
// ARRANGE: Test various counts
|
|
259
|
-
class ParentWorkflow extends Workflow {
|
|
260
|
-
@Task({
|
|
261
|
-
concurrent: true,
|
|
262
|
-
errorMergeStrategy: { enabled: true },
|
|
263
|
-
})
|
|
264
|
-
async spawnChildren() {
|
|
265
|
-
return [
|
|
266
|
-
createChildWorkflow(this, 'Success1', false),
|
|
267
|
-
createChildWorkflow(this, 'Fail1', true),
|
|
268
|
-
createChildWorkflow(this, 'Success2', false),
|
|
269
|
-
createChildWorkflow(this, 'Fail2', true),
|
|
270
|
-
createChildWorkflow(this, 'Fail3', true),
|
|
271
|
-
];
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
async run() {
|
|
275
|
-
try {
|
|
276
|
-
await this.spawnChildren();
|
|
277
|
-
} catch (err) {
|
|
278
|
-
return err;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
const parent = new ParentWorkflow('Parent');
|
|
284
|
-
const thrownError = await parent.run() as WorkflowError;
|
|
285
|
-
|
|
286
|
-
// ASSERT: Message format "${X} of ${Y} concurrent child workflows failed in task '${taskName}'"
|
|
287
|
-
expect(thrownError.message).toBe("3 of 5 concurrent child workflows failed in task 'spawnChildren'");
|
|
288
|
-
expect(thrownError.message).toMatch(/\d+ of \d+ concurrent child workflows failed/);
|
|
289
|
-
expect(thrownError.message).toContain("task 'spawnChildren'");
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
it('should aggregate all logs from all failed workflows', async () => {
|
|
293
|
-
// ARRANGE: Create workflows that log before failing
|
|
294
|
-
class LoggingWorkflow extends Workflow {
|
|
295
|
-
constructor(name: string, parent: Workflow, private shouldFail: boolean) {
|
|
296
|
-
super(name, parent);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
@Step()
|
|
300
|
-
async executeStep() {
|
|
301
|
-
this.logger.info(`${this.node.name} starting`);
|
|
302
|
-
if (this.shouldFail) {
|
|
303
|
-
this.logger.error(`${this.node.name} failing`);
|
|
304
|
-
throw new Error(`${this.node.name} failed`);
|
|
305
|
-
}
|
|
306
|
-
this.logger.info(`${this.node.name} completed`);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
async run() {
|
|
310
|
-
return this.executeStep();
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
class ParentWorkflow extends Workflow {
|
|
315
|
-
@Task({
|
|
316
|
-
concurrent: true,
|
|
317
|
-
errorMergeStrategy: { enabled: true },
|
|
318
|
-
})
|
|
319
|
-
async spawnChildren() {
|
|
320
|
-
return [
|
|
321
|
-
new LoggingWorkflow('Workflow-1', this, true),
|
|
322
|
-
new LoggingWorkflow('Workflow-2', this, true),
|
|
323
|
-
new LoggingWorkflow('Workflow-3', this, false),
|
|
324
|
-
];
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
async run() {
|
|
328
|
-
try {
|
|
329
|
-
await this.spawnChildren();
|
|
330
|
-
} catch (err) {
|
|
331
|
-
return err;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
const parent = new ParentWorkflow('Parent');
|
|
337
|
-
const thrownError = (await parent.run()) as WorkflowError;
|
|
338
|
-
|
|
339
|
-
// ASSERT: Logs from both failed workflows aggregated
|
|
340
|
-
expect(thrownError.logs).toBeDefined();
|
|
341
|
-
const logMessages = thrownError.logs.map((l) => l.message);
|
|
342
|
-
|
|
343
|
-
// Should have logs from both failing workflows
|
|
344
|
-
expect(logMessages.some((m) => m.includes('Workflow-1'))).toBe(true);
|
|
345
|
-
expect(logMessages.some((m) => m.includes('Workflow-2'))).toBe(true);
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
it('should include metadata in original field', async () => {
|
|
349
|
-
// ARRANGE: Test metadata structure
|
|
350
|
-
class ParentWorkflow extends Workflow {
|
|
351
|
-
@Task({
|
|
352
|
-
concurrent: true,
|
|
353
|
-
errorMergeStrategy: { enabled: true },
|
|
354
|
-
})
|
|
355
|
-
async spawnChildren() {
|
|
356
|
-
return [
|
|
357
|
-
createChildWorkflow(this, 'W1', true),
|
|
358
|
-
createChildWorkflow(this, 'W2', true),
|
|
359
|
-
createChildWorkflow(this, 'W3', true),
|
|
360
|
-
];
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
async run() {
|
|
364
|
-
try {
|
|
365
|
-
await this.spawnChildren();
|
|
366
|
-
} catch (err) {
|
|
367
|
-
return err;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
const parent = new ParentWorkflow('Parent');
|
|
373
|
-
const thrownError = (await parent.run()) as WorkflowError;
|
|
374
|
-
|
|
375
|
-
// ASSERT: Metadata structure is correct
|
|
376
|
-
const metadata = thrownError.original as {
|
|
377
|
-
name: string;
|
|
378
|
-
message: string;
|
|
379
|
-
errors: WorkflowError[];
|
|
380
|
-
totalChildren: number;
|
|
381
|
-
failedChildren: number;
|
|
382
|
-
failedWorkflowIds: string[];
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
expect(metadata.name).toBe('WorkflowAggregateError');
|
|
386
|
-
expect(metadata.message).toContain('concurrent child workflows failed');
|
|
387
|
-
expect(metadata.errors).toHaveLength(3);
|
|
388
|
-
expect(metadata.totalChildren).toBe(3);
|
|
389
|
-
expect(metadata.failedChildren).toBe(3);
|
|
390
|
-
expect(metadata.failedWorkflowIds).toHaveLength(3);
|
|
391
|
-
|
|
392
|
-
// ASSERT: Each error in metadata has workflowId
|
|
393
|
-
metadata.failedWorkflowIds.forEach((id) => {
|
|
394
|
-
expect(id).toBeDefined();
|
|
395
|
-
expect(typeof id).toBe('string');
|
|
396
|
-
});
|
|
397
|
-
});
|
|
398
|
-
});
|
|
399
|
-
|
|
400
|
-
describe('Enabled with custom combine function', () => {
|
|
401
|
-
it('should call custom combine function when provided', async () => {
|
|
402
|
-
// ARRANGE: Create spy for combine function
|
|
403
|
-
const combineSpy = vi.fn((errors: WorkflowError[]) => ({
|
|
404
|
-
message: `Custom merge: ${errors.length} errors`,
|
|
405
|
-
original: errors,
|
|
406
|
-
workflowId: 'custom-parent',
|
|
407
|
-
logs: errors.flatMap((e) => e.logs),
|
|
408
|
-
stack: errors[0]?.stack,
|
|
409
|
-
state: errors[0]?.state || {},
|
|
410
|
-
}));
|
|
411
|
-
|
|
412
|
-
class ParentWorkflow extends Workflow {
|
|
413
|
-
@Task({
|
|
414
|
-
concurrent: true,
|
|
415
|
-
errorMergeStrategy: {
|
|
416
|
-
enabled: true,
|
|
417
|
-
combine: combineSpy, // Custom combine function
|
|
418
|
-
},
|
|
419
|
-
})
|
|
420
|
-
async spawnChildren() {
|
|
421
|
-
return [
|
|
422
|
-
createChildWorkflow(this, 'Alpha', true),
|
|
423
|
-
createChildWorkflow(this, 'Beta', true),
|
|
424
|
-
createChildWorkflow(this, 'Gamma', false),
|
|
425
|
-
];
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
async run() {
|
|
429
|
-
try {
|
|
430
|
-
await this.spawnChildren();
|
|
431
|
-
} catch (err) {
|
|
432
|
-
return err;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
const parent = new ParentWorkflow('Parent');
|
|
438
|
-
|
|
439
|
-
// ACT
|
|
440
|
-
await parent.run();
|
|
441
|
-
|
|
442
|
-
// ASSERT: Custom combine function was called
|
|
443
|
-
expect(combineSpy).toHaveBeenCalledTimes(1);
|
|
444
|
-
|
|
445
|
-
// ASSERT: Called with array of WorkflowError objects
|
|
446
|
-
const calls = combineSpy.mock.calls;
|
|
447
|
-
expect(calls).toHaveLength(1);
|
|
448
|
-
const errorsArg = calls[0][0] as WorkflowError[];
|
|
449
|
-
expect(Array.isArray(errorsArg)).toBe(true);
|
|
450
|
-
expect(errorsArg).toHaveLength(2); // Alpha and Beta failed
|
|
451
|
-
});
|
|
452
|
-
|
|
453
|
-
it('should use custom merge result from combine function', async () => {
|
|
454
|
-
// ARRANGE: Custom combine that returns specific format
|
|
455
|
-
const customMerger = (errors: WorkflowError[]): WorkflowError => ({
|
|
456
|
-
message: `MERGED: ${errors.map((e) => e.message).join(' | ')}`,
|
|
457
|
-
original: {
|
|
458
|
-
customField: 'custom-value',
|
|
459
|
-
errors,
|
|
460
|
-
},
|
|
461
|
-
workflowId: 'merged-workflow',
|
|
462
|
-
logs: errors.flatMap((e) => e.logs),
|
|
463
|
-
stack: errors[0]?.stack,
|
|
464
|
-
state: errors[0]?.state || {},
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
class ParentWorkflow extends Workflow {
|
|
468
|
-
@Task({
|
|
469
|
-
concurrent: true,
|
|
470
|
-
errorMergeStrategy: {
|
|
471
|
-
enabled: true,
|
|
472
|
-
combine: customMerger,
|
|
473
|
-
},
|
|
474
|
-
})
|
|
475
|
-
async spawnChildren() {
|
|
476
|
-
return [
|
|
477
|
-
createChildWorkflow(this, 'First', true),
|
|
478
|
-
createChildWorkflow(this, 'Second', true),
|
|
479
|
-
];
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
async run() {
|
|
483
|
-
try {
|
|
484
|
-
await this.spawnChildren();
|
|
485
|
-
} catch (err) {
|
|
486
|
-
return err;
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
const parent = new ParentWorkflow('Parent');
|
|
492
|
-
const thrownError = (await parent.run()) as WorkflowError;
|
|
493
|
-
|
|
494
|
-
// ASSERT: Custom merge result used
|
|
495
|
-
expect(thrownError.message).toBe('MERGED: First failed | Second failed');
|
|
496
|
-
expect(thrownError.workflowId).toBe('merged-workflow');
|
|
497
|
-
|
|
498
|
-
// ASSERT: Custom fields preserved
|
|
499
|
-
const customMetadata = thrownError.original as { customField: string };
|
|
500
|
-
expect(customMetadata.customField).toBe('custom-value');
|
|
501
|
-
});
|
|
502
|
-
|
|
503
|
-
it('should pass all errors to custom combine function', async () => {
|
|
504
|
-
// ARRANGE: Track which errors were passed
|
|
505
|
-
let receivedErrors: WorkflowError[] = [];
|
|
506
|
-
|
|
507
|
-
const trackingMerger = (errors: WorkflowError[]): WorkflowError => {
|
|
508
|
-
receivedErrors = errors;
|
|
509
|
-
return createMockWorkflowError({
|
|
510
|
-
message: `Tracked ${errors.length} errors`,
|
|
511
|
-
});
|
|
512
|
-
};
|
|
513
|
-
|
|
514
|
-
class ParentWorkflow extends Workflow {
|
|
515
|
-
@Task({
|
|
516
|
-
concurrent: true,
|
|
517
|
-
errorMergeStrategy: {
|
|
518
|
-
enabled: true,
|
|
519
|
-
combine: trackingMerger,
|
|
520
|
-
},
|
|
521
|
-
})
|
|
522
|
-
async spawnChildren() {
|
|
523
|
-
return [
|
|
524
|
-
createChildWorkflow(this, 'A', true),
|
|
525
|
-
createChildWorkflow(this, 'B', true),
|
|
526
|
-
createChildWorkflow(this, 'C', true),
|
|
527
|
-
createChildWorkflow(this, 'D', false),
|
|
528
|
-
];
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
async run() {
|
|
532
|
-
try {
|
|
533
|
-
await this.spawnChildren();
|
|
534
|
-
} catch (err) {
|
|
535
|
-
return err;
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
const parent = new ParentWorkflow('Parent');
|
|
541
|
-
await parent.run();
|
|
542
|
-
|
|
543
|
-
// ASSERT: All failed errors passed to combine
|
|
544
|
-
expect(receivedErrors).toHaveLength(3);
|
|
545
|
-
const errorMessages = receivedErrors.map((e) => e.message);
|
|
546
|
-
expect(errorMessages).toContain('A failed');
|
|
547
|
-
expect(errorMessages).toContain('B failed');
|
|
548
|
-
expect(errorMessages).toContain('C failed');
|
|
549
|
-
});
|
|
550
|
-
});
|
|
551
|
-
|
|
552
|
-
describe('Edge cases and error scenarios', () => {
|
|
553
|
-
it('should handle single failure with merge enabled', async () => {
|
|
554
|
-
class ParentWorkflow extends Workflow {
|
|
555
|
-
@Task({
|
|
556
|
-
concurrent: true,
|
|
557
|
-
errorMergeStrategy: { enabled: true },
|
|
558
|
-
})
|
|
559
|
-
async spawnChildren() {
|
|
560
|
-
return [createChildWorkflow(this, 'OnlyChild', true)];
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
async run() {
|
|
564
|
-
try {
|
|
565
|
-
await this.spawnChildren();
|
|
566
|
-
} catch (err) {
|
|
567
|
-
return err;
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
const parent = new ParentWorkflow('Parent');
|
|
573
|
-
const thrownError = (await parent.run()) as WorkflowError;
|
|
574
|
-
|
|
575
|
-
// ASSERT: Message format correct for single failure
|
|
576
|
-
expect(thrownError.message).toBe("1 of 1 concurrent child workflows failed in task 'spawnChildren'");
|
|
577
|
-
});
|
|
578
|
-
|
|
579
|
-
it('should handle all workflows failing with merge enabled', async () => {
|
|
580
|
-
class ParentWorkflow extends Workflow {
|
|
581
|
-
@Task({
|
|
582
|
-
concurrent: true,
|
|
583
|
-
errorMergeStrategy: { enabled: true },
|
|
584
|
-
})
|
|
585
|
-
async spawnChildren() {
|
|
586
|
-
return [
|
|
587
|
-
createChildWorkflow(this, 'W1', true),
|
|
588
|
-
createChildWorkflow(this, 'W2', true),
|
|
589
|
-
createChildWorkflow(this, 'W3', true),
|
|
590
|
-
createChildWorkflow(this, 'W4', true),
|
|
591
|
-
];
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
async run() {
|
|
595
|
-
try {
|
|
596
|
-
await this.spawnChildren();
|
|
597
|
-
} catch (err) {
|
|
598
|
-
return err;
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
const parent = new ParentWorkflow('Parent');
|
|
604
|
-
const thrownError = (await parent.run()) as WorkflowError;
|
|
605
|
-
|
|
606
|
-
// ASSERT: All failures counted
|
|
607
|
-
expect(thrownError.message).toBe("4 of 4 concurrent child workflows failed in task 'spawnChildren'");
|
|
608
|
-
|
|
609
|
-
// ASSERT: All workflows completed
|
|
610
|
-
expect(parent.children.length).toBe(4);
|
|
611
|
-
});
|
|
612
|
-
|
|
613
|
-
it('should handle mixed success/failure with merge enabled', async () => {
|
|
614
|
-
class ParentWorkflow extends Workflow {
|
|
615
|
-
@Task({
|
|
616
|
-
concurrent: true,
|
|
617
|
-
errorMergeStrategy: { enabled: true },
|
|
618
|
-
})
|
|
619
|
-
async spawnChildren() {
|
|
620
|
-
return [
|
|
621
|
-
createChildWorkflow(this, 'Success1', false),
|
|
622
|
-
createChildWorkflow(this, 'Fail1', true),
|
|
623
|
-
createChildWorkflow(this, 'Success2', false),
|
|
624
|
-
createChildWorkflow(this, 'Fail2', true),
|
|
625
|
-
createChildWorkflow(this, 'Success3', false),
|
|
626
|
-
];
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
async run() {
|
|
630
|
-
try {
|
|
631
|
-
await this.spawnChildren();
|
|
632
|
-
} catch (err) {
|
|
633
|
-
return err;
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
const parent = new ParentWorkflow('Parent');
|
|
639
|
-
const thrownError = (await parent.run()) as WorkflowError;
|
|
640
|
-
|
|
641
|
-
// ASSERT: Only failed children counted in message
|
|
642
|
-
expect(thrownError.message).toBe("2 of 5 concurrent child workflows failed in task 'spawnChildren'");
|
|
643
|
-
|
|
644
|
-
// ASSERT: All workflows completed
|
|
645
|
-
expect(parent.children.length).toBe(5);
|
|
646
|
-
|
|
647
|
-
// ASSERT: Metadata correct
|
|
648
|
-
const metadata = thrownError.original as { failedChildren: number; totalChildren: number };
|
|
649
|
-
expect(metadata.failedChildren).toBe(2);
|
|
650
|
-
expect(metadata.totalChildren).toBe(5);
|
|
651
|
-
});
|
|
652
|
-
|
|
653
|
-
it('should complete all workflows even when errors occur', async () => {
|
|
654
|
-
const completedWorkflows = new Set<string>();
|
|
655
|
-
|
|
656
|
-
class ParentWorkflow extends Workflow {
|
|
657
|
-
@Task({
|
|
658
|
-
concurrent: true,
|
|
659
|
-
errorMergeStrategy: { enabled: true },
|
|
660
|
-
})
|
|
661
|
-
async spawnChildren() {
|
|
662
|
-
const children = [
|
|
663
|
-
createChildWorkflow(this, 'Success1', false),
|
|
664
|
-
createChildWorkflow(this, 'Fail1', true),
|
|
665
|
-
createChildWorkflow(this, 'Success2', false),
|
|
666
|
-
createChildWorkflow(this, 'Fail2', true),
|
|
667
|
-
];
|
|
668
|
-
|
|
669
|
-
// Track completion
|
|
670
|
-
children.forEach((child) => {
|
|
671
|
-
child.run().then(
|
|
672
|
-
() => completedWorkflows.add(child.id),
|
|
673
|
-
() => completedWorkflows.add(child.id)
|
|
674
|
-
);
|
|
675
|
-
});
|
|
676
|
-
|
|
677
|
-
return children;
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
async run() {
|
|
681
|
-
try {
|
|
682
|
-
await this.spawnChildren();
|
|
683
|
-
} catch (err) {
|
|
684
|
-
// Expected
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
const parent = new ParentWorkflow('Parent');
|
|
690
|
-
await parent.run();
|
|
691
|
-
|
|
692
|
-
// ASSERT: All workflows completed (no orphans)
|
|
693
|
-
expect(completedWorkflows.size).toBe(4);
|
|
694
|
-
expect(parent.children.length).toBe(4);
|
|
695
|
-
});
|
|
696
|
-
|
|
697
|
-
it('should emit error event with merged error', async () => {
|
|
698
|
-
class ParentWorkflow extends Workflow {
|
|
699
|
-
@Task({
|
|
700
|
-
concurrent: true,
|
|
701
|
-
errorMergeStrategy: { enabled: true },
|
|
702
|
-
})
|
|
703
|
-
async spawnChildren() {
|
|
704
|
-
return [
|
|
705
|
-
createChildWorkflow(this, 'OK', false),
|
|
706
|
-
createChildWorkflow(this, 'Bad1', true),
|
|
707
|
-
createChildWorkflow(this, 'Bad2', true),
|
|
708
|
-
];
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
async run() {
|
|
712
|
-
try {
|
|
713
|
-
await this.spawnChildren();
|
|
714
|
-
} catch (err) {
|
|
715
|
-
return err;
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
const parent = new ParentWorkflow('Parent');
|
|
721
|
-
const events = setupEventObserver(parent);
|
|
722
|
-
await parent.run();
|
|
723
|
-
|
|
724
|
-
// ASSERT: Error events emitted for individual failures
|
|
725
|
-
const individualErrorEvents = events.filter((e) => {
|
|
726
|
-
if (e.type === 'error') {
|
|
727
|
-
return e.error.message === 'Bad1 failed' || e.error.message === 'Bad2 failed';
|
|
728
|
-
}
|
|
729
|
-
return false;
|
|
730
|
-
});
|
|
731
|
-
expect(individualErrorEvents.length).toBeGreaterThanOrEqual(2);
|
|
732
|
-
|
|
733
|
-
// ASSERT: Additional merged error event emitted
|
|
734
|
-
const mergedErrorEvent = events.find((e) => {
|
|
735
|
-
if (e.type === 'error') {
|
|
736
|
-
return e.error.message.includes('concurrent child workflows failed');
|
|
737
|
-
}
|
|
738
|
-
return false;
|
|
739
|
-
});
|
|
740
|
-
expect(mergedErrorEvent).toBeDefined();
|
|
741
|
-
|
|
742
|
-
// ASSERT: Merged error has correct structure
|
|
743
|
-
if (mergedErrorEvent && mergedErrorEvent.type === 'error') {
|
|
744
|
-
expect(mergedErrorEvent.error.message).toContain('2 of 3');
|
|
745
|
-
expect(mergedErrorEvent.error.workflowId).toBeDefined();
|
|
746
|
-
expect(Array.isArray(mergedErrorEvent.error.logs)).toBe(true);
|
|
747
|
-
}
|
|
748
|
-
});
|
|
749
|
-
});
|
|
750
|
-
|
|
751
|
-
describe.skip('maxMergeDepth validation', () => {
|
|
752
|
-
// NOTE: maxMergeDepth is defined in ErrorMergeStrategy interface
|
|
753
|
-
// but not currently implemented in src/decorators/task.ts
|
|
754
|
-
// These tests should be implemented when maxMergeDepth is added
|
|
755
|
-
|
|
756
|
-
it('should respect maxMergeDepth when merging nested errors');
|
|
757
|
-
it('should handle maxMergeDepth=0 (no merging)');
|
|
758
|
-
it('should handle maxMergeDepth=1 (single level merging)');
|
|
759
|
-
});
|
|
760
|
-
});
|