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,1066 +0,0 @@
|
|
|
1
|
-
name: "P1.M2.T2.S2 - Implement Error Aggregation Logic in @Task Decorator"
|
|
2
|
-
description: |
|
|
3
|
-
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
## Goal
|
|
7
|
-
|
|
8
|
-
**Feature Goal**: Implement error aggregation logic in the @Task decorator to support the `errorMergeStrategy` option, enabling users to configure how multiple concurrent workflow errors are merged and propagated.
|
|
9
|
-
|
|
10
|
-
**Deliverable**: Updated @Task decorator (`src/decorators/task.ts`) that:
|
|
11
|
-
|
|
12
|
-
1. Checks if `opts.errorMergeStrategy?.enabled` is true after collecting errors from Promise.allSettled()
|
|
13
|
-
2. Calls `opts.errorMergeStrategy.combine?(errors)` if provided, otherwise uses a default error merger
|
|
14
|
-
3. Throws the merged error instead of the first error when error merge strategy is enabled
|
|
15
|
-
4. Emits error event with the merged error (single event for all failures)
|
|
16
|
-
|
|
17
|
-
**Success Definition**:
|
|
18
|
-
|
|
19
|
-
* When `errorMergeStrategy?.enabled === true`, all concurrent workflow errors are aggregated
|
|
20
|
-
* When `combine()` function is provided, it is called with array of WorkflowError objects
|
|
21
|
-
* When `combine()` is not provided, a default merger creates an AggregateError-like structure
|
|
22
|
-
* The merged error contains aggregated information from all failures
|
|
23
|
-
* A single error event is emitted with the merged error
|
|
24
|
-
* Backward compatibility is maintained: when `errorMergeStrategy` is not provided, first error is thrown
|
|
25
|
-
* All existing tests continue to pass
|
|
26
|
-
|
|
27
|
-
## User Persona (if applicable)
|
|
28
|
-
|
|
29
|
-
**Target User**: Library Developer / Workflow Architect
|
|
30
|
-
|
|
31
|
-
**Use Case**: A developer running concurrent child workflows wants to receive comprehensive error information when multiple workflows fail, instead of just the first error.
|
|
32
|
-
|
|
33
|
-
**User Journey**:
|
|
34
|
-
|
|
35
|
-
1. Developer creates a parent workflow with multiple concurrent child workflows
|
|
36
|
-
2. Some child workflows fail
|
|
37
|
-
3. Developer wants to see ALL errors, not just the first one
|
|
38
|
-
4. Developer enables `errorMergeStrategy: { enabled: true }` in @Task decorator options
|
|
39
|
-
5. Developer optionally provides a custom `combine()` function to merge errors
|
|
40
|
-
6. When failures occur, all errors are aggregated and thrown as a single merged error
|
|
41
|
-
7. Developer can inspect the merged error to see all failures
|
|
42
|
-
|
|
43
|
-
**Pain Points Addressed**:
|
|
44
|
-
|
|
45
|
-
* Currently only the first error from concurrent failures is visible
|
|
46
|
-
* Other concurrent failures are collected but not surfaced to the caller
|
|
47
|
-
* No way to customize how multiple errors should be merged
|
|
48
|
-
* Difficult to debug when multiple independent workflows fail
|
|
49
|
-
|
|
50
|
-
## Why
|
|
51
|
-
|
|
52
|
-
* **Observability**: Multiple concurrent failures should be visible together, not hidden
|
|
53
|
-
* **Debugging**: Developers need to see ALL errors to understand patterns and root causes
|
|
54
|
-
* **Production Patterns**: Aligns with workflow engines like Airflow (trigger rules) and Step Functions (parallel error aggregation)
|
|
55
|
-
* **PRD Compliance**: PRD Section 10 specifies "Optional Multi-Error Merging" as a feature
|
|
56
|
-
* **Enable P1.M2.T2.S3**: Default error merger implementation depends on this being complete
|
|
57
|
-
* **Enable P1.M2.T2.S4**: ErrorMergeStrategy tests depend on this implementation
|
|
58
|
-
|
|
59
|
-
## What
|
|
60
|
-
|
|
61
|
-
Modify the @Task decorator in `src/decorators/task.ts` to implement error aggregation logic when `errorMergeStrategy.enabled === true`.
|
|
62
|
-
|
|
63
|
-
### Current Implementation (Lines 111-121)
|
|
64
|
-
|
|
65
|
-
```typescript
|
|
66
|
-
if (runnable.length > 0) {
|
|
67
|
-
const results = await Promise.allSettled(runnable.map((w) => w.run()));
|
|
68
|
-
|
|
69
|
-
const rejected = results.filter(
|
|
70
|
-
(r): r is PromiseRejectedResult => r.status === 'rejected'
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
if (rejected.length > 0) {
|
|
74
|
-
throw rejected[0].reason; // First error wins (backward compatible)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### Target Implementation
|
|
80
|
-
|
|
81
|
-
```typescript
|
|
82
|
-
if (runnable.length > 0) {
|
|
83
|
-
const results = await Promise.allSettled(runnable.map((w) => w.run()));
|
|
84
|
-
|
|
85
|
-
const rejected = results.filter(
|
|
86
|
-
(r): r is PromiseRejectedResult => r.status === 'rejected'
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
if (rejected.length > 0) {
|
|
90
|
-
// Check if error merge strategy is enabled
|
|
91
|
-
if (opts.errorMergeStrategy?.enabled) {
|
|
92
|
-
// Extract WorkflowError objects from rejected promises
|
|
93
|
-
const errors = rejected.map((r) => r.reason as WorkflowError);
|
|
94
|
-
|
|
95
|
-
// Merge errors using custom combine() or default merger
|
|
96
|
-
const mergedError = opts.errorMergeStrategy?.combine
|
|
97
|
-
? opts.errorMergeStrategy.combine(errors)
|
|
98
|
-
: defaultErrorMerger(errors, taskName, wf.id, runnable.length);
|
|
99
|
-
|
|
100
|
-
// Emit error event with merged error
|
|
101
|
-
wf.emitEvent({
|
|
102
|
-
type: 'error',
|
|
103
|
-
node: wf.node,
|
|
104
|
-
error: mergedError,
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
// Throw merged error
|
|
108
|
-
throw mergedError;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Backward compatibility: throw first error
|
|
112
|
-
throw rejected[0].reason;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### Success Criteria
|
|
118
|
-
|
|
119
|
-
* [ ] Check `opts.errorMergeStrategy?.enabled` before throwing error
|
|
120
|
-
* [ ] Extract WorkflowError array from rejected promises
|
|
121
|
-
* [ ] Call custom `combine()` function if provided
|
|
122
|
-
* [ ] Use default error merger when `combine()` is not provided
|
|
123
|
-
* [ ] Emit error event with merged error (not first error)
|
|
124
|
-
* [ ] Throw merged error instead of first error when enabled
|
|
125
|
-
* [ ] Backward compatibility maintained when `errorMergeStrategy` not provided
|
|
126
|
-
* [ ] All existing tests pass
|
|
127
|
-
* [ ] New tests for error aggregation pass
|
|
128
|
-
|
|
129
|
-
## All Needed Context
|
|
130
|
-
|
|
131
|
-
### Context Completeness Check
|
|
132
|
-
|
|
133
|
-
**"No Prior Knowledge" Test**: If someone knew nothing about this codebase, would they have everything needed to implement this successfully?
|
|
134
|
-
|
|
135
|
-
**Answer**: YES - This PRP provides:
|
|
136
|
-
|
|
137
|
-
* Exact file location with line numbers (src/decorators/task.ts:111-121)
|
|
138
|
-
* Complete current implementation code
|
|
139
|
-
* Type definitions for all interfaces used
|
|
140
|
-
* Error handling patterns to follow
|
|
141
|
-
* Default error merger implementation
|
|
142
|
-
* Test patterns for validation
|
|
143
|
-
* External research documentation with URLs
|
|
144
|
-
|
|
145
|
-
### Documentation & References
|
|
146
|
-
|
|
147
|
-
```yaml
|
|
148
|
-
# MUST READ - Current Implementation
|
|
149
|
-
- file: src/decorators/task.ts
|
|
150
|
-
lines: 104-122
|
|
151
|
-
why: Target section to modify - contains Promise.allSettled error handling
|
|
152
|
-
pattern: Error collection with rejected.filter() and first-error-wins throw
|
|
153
|
-
gotcha: rejected[].reason is already WorkflowError (wrapped by @Step decorator)
|
|
154
|
-
|
|
155
|
-
- file: src/decorators/task.ts
|
|
156
|
-
lines: 1-136 (full file)
|
|
157
|
-
why: Complete @Task decorator context including imports and event emission
|
|
158
|
-
pattern: Task decorator wrapper with event emission and child attachment
|
|
159
|
-
|
|
160
|
-
- file: src/types/decorators.ts
|
|
161
|
-
why: TaskOptions interface definition - errorMergeStrategy field added in P1.M2.T2.S1
|
|
162
|
-
current_content: |
|
|
163
|
-
import type { ErrorMergeStrategy } from './error-strategy.js';
|
|
164
|
-
|
|
165
|
-
export interface TaskOptions {
|
|
166
|
-
name?: string;
|
|
167
|
-
concurrent?: boolean;
|
|
168
|
-
errorMergeStrategy?: ErrorMergeStrategy;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
- file: src/types/error-strategy.ts
|
|
172
|
-
why: ErrorMergeStrategy interface definition
|
|
173
|
-
current_content: |
|
|
174
|
-
import type { WorkflowError } from './error.js';
|
|
175
|
-
|
|
176
|
-
export interface ErrorMergeStrategy {
|
|
177
|
-
enabled: boolean;
|
|
178
|
-
maxMergeDepth?: number;
|
|
179
|
-
combine?(errors: WorkflowError[]): WorkflowError;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
- file: src/types/error.ts
|
|
183
|
-
why: WorkflowError interface structure - what errors look like in this codebase
|
|
184
|
-
current_content: |
|
|
185
|
-
export interface WorkflowError {
|
|
186
|
-
message: string;
|
|
187
|
-
original: unknown;
|
|
188
|
-
workflowId: string;
|
|
189
|
-
stack?: string;
|
|
190
|
-
state: SerializedWorkflowState;
|
|
191
|
-
logs: LogEntry[];
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
- file: src/types/events.ts
|
|
195
|
-
why: WorkflowEvent union type - error event structure
|
|
196
|
-
current_content: |
|
|
197
|
-
| { type: 'error'; node: WorkflowNode; error: WorkflowError }
|
|
198
|
-
|
|
199
|
-
- file: src/decorators/step.ts
|
|
200
|
-
lines: 109-134
|
|
201
|
-
why: Shows how WorkflowError objects are created and error events emitted
|
|
202
|
-
pattern: Error capture with getObservedState(), event emission
|
|
203
|
-
critical: Each failing workflow already emits error event - don't duplicate
|
|
204
|
-
|
|
205
|
-
# ARCHITECTURE DOCUMENTATION - Implementation Guidance
|
|
206
|
-
- docfile: plan/001_d3bb02af4886/bugfix/architecture/concurrent_execution_best_practices.md
|
|
207
|
-
why: Internal guidance on error aggregation strategies
|
|
208
|
-
section: Lines 597-638 ("Groundswell Implementation Recommendation")
|
|
209
|
-
critical: |
|
|
210
|
-
Shows recommended implementation pattern:
|
|
211
|
-
- Check opts.errorMergeStrategy?.enabled
|
|
212
|
-
- Call opts.errorMergeStrategy.combine?(errors)
|
|
213
|
-
- Throw merged error instead of first error
|
|
214
|
-
- Emit error event with merged error
|
|
215
|
-
|
|
216
|
-
# EXTERNAL RESEARCH - Error Aggregation Patterns
|
|
217
|
-
- url: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled
|
|
218
|
-
why: Official documentation for Promise.allSettled() method
|
|
219
|
-
section: #description
|
|
220
|
-
critical: Promise.allSettled ALWAYS resolves - manual error checking required
|
|
221
|
-
|
|
222
|
-
- url: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError
|
|
223
|
-
why: Official documentation for AggregateError - useful pattern reference
|
|
224
|
-
section: #description
|
|
225
|
-
critical: AggregateError can contain multiple errors as cause chain
|
|
226
|
-
|
|
227
|
-
- docfile: plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S2/research/05_comprehensive_summary.md
|
|
228
|
-
why: Comprehensive summary of external research findings
|
|
229
|
-
section: "Recommended Implementation for Groundswell"
|
|
230
|
-
critical: Complete code examples for error aggregation patterns
|
|
231
|
-
|
|
232
|
-
- docfile: plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S2/research/01_typescript_error_aggregation_patterns.md
|
|
233
|
-
why: TypeScript-specific error aggregation patterns
|
|
234
|
-
section: "Production-Grade Patterns"
|
|
235
|
-
critical: Type guards, error normalization, context preservation
|
|
236
|
-
|
|
237
|
-
# PREVIOUS PRPS - Understanding What Was Done Before
|
|
238
|
-
- docfile: plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S1/PRP.md
|
|
239
|
-
why: P1.M2.T2.S1 added errorMergeStrategy field to TaskOptions
|
|
240
|
-
section: "What" section shows Target State
|
|
241
|
-
critical: TaskOptions interface now has errorMergeStrategy?: ErrorMergeStrategy field
|
|
242
|
-
|
|
243
|
-
- docfile: plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S2/PRP.md
|
|
244
|
-
why: P1.M2.T1.S2 implemented Promise.allSettled with error collection
|
|
245
|
-
section: "Implementation Blueprint" shows the replaced Promise.all logic
|
|
246
|
-
critical: rejected array already available - just need to aggregate it
|
|
247
|
-
|
|
248
|
-
# TEST PATTERNS - Follow for Validation
|
|
249
|
-
- file: src/__tests__/adversarial/concurrent-task-failures.test.ts
|
|
250
|
-
why: Tests for concurrent task failure scenarios
|
|
251
|
-
pattern: Testing multiple failing workflows with error verification
|
|
252
|
-
|
|
253
|
-
- file: src/__tests__/adversarial/edge-case.test.ts
|
|
254
|
-
lines: 366-430
|
|
255
|
-
why: Contains concurrent task execution tests with mixed success/failure
|
|
256
|
-
pattern: Testing concurrent workflows with errors
|
|
257
|
-
|
|
258
|
-
- docfile: plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S2/research/RESEARCH_REPORT.md
|
|
259
|
-
why: Complete testing guide for error aggregation
|
|
260
|
-
section: "Key Research Findings" and "Best Practices Summary"
|
|
261
|
-
critical: Test patterns, assertion patterns, edge cases to cover
|
|
262
|
-
|
|
263
|
-
# TYPE REFERENCES - TypeScript Type Safety
|
|
264
|
-
- url: https://www.typescriptlang.org/docs/handbook/2/narrowing.html#type-predicates
|
|
265
|
-
why: TypeScript type guard documentation
|
|
266
|
-
section: Type Predicates
|
|
267
|
-
critical: Type guard pattern: (r): r is PromiseRejectedResult => r.status === 'rejected'
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
### Current Codebase Tree
|
|
271
|
-
|
|
272
|
-
```bash
|
|
273
|
-
/home/dustin/projects/groundswell
|
|
274
|
-
├── src/
|
|
275
|
-
│ ├── decorators/
|
|
276
|
-
│ │ ├── index.ts # Exports Task decorator
|
|
277
|
-
│ │ ├── step.ts # @Step decorator with error wrapping (lines 109-134)
|
|
278
|
-
│ │ └── task.ts # PRIMARY: Lines 111-121 to modify - TARGET FILE
|
|
279
|
-
│ ├── types/
|
|
280
|
-
│ │ ├── index.ts # Re-exports all types
|
|
281
|
-
│ │ ├── decorators.ts # TaskOptions with errorMergeStrategy field (from P1.M2.T2.S1)
|
|
282
|
-
│ │ ├── error-strategy.ts # ErrorMergeStrategy interface
|
|
283
|
-
│ │ ├── error.ts # WorkflowError interface
|
|
284
|
-
│ │ └── events.ts # WorkflowEvent union type with error event
|
|
285
|
-
│ └── __tests__/
|
|
286
|
-
│ ├── adversarial/
|
|
287
|
-
│ │ ├── concurrent-task-failures.test.ts # P1.M2.T1.S3 tests
|
|
288
|
-
│ │ └── edge-case.test.ts # Concurrent execution tests
|
|
289
|
-
│ └── unit/
|
|
290
|
-
│ └── decorators.test.ts # General decorator tests
|
|
291
|
-
├── plan/
|
|
292
|
-
│ └── 001_d3bb02af4886/
|
|
293
|
-
│ ├── bugfix/
|
|
294
|
-
│ │ └── 001_e8e04329daf3/
|
|
295
|
-
│ │ ├── P1M2T2S2/
|
|
296
|
-
│ │ │ ├── research/ # External research storage
|
|
297
|
-
│ │ │ └── PRP.md # ← THIS FILE
|
|
298
|
-
│ │ └── architecture/
|
|
299
|
-
│ │ └── concurrent_execution_best_practices.md
|
|
300
|
-
└── vitest.config.ts # Test configuration
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
### Desired Codebase Tree (Changes for This Task)
|
|
304
|
-
|
|
305
|
-
```bash
|
|
306
|
-
# MODIFIED FILES:
|
|
307
|
-
src/decorators/task.ts # Add error aggregation logic (lines 111-121)
|
|
308
|
-
|
|
309
|
-
# NO NEW FILES for this task
|
|
310
|
-
# P1.M2.T2.S3 will add default error merger utility
|
|
311
|
-
# P1.M2.T2.S4 will add tests for ErrorMergeStrategy functionality
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
### Known Gotchas of Our Codebase & Library Quirks
|
|
315
|
-
|
|
316
|
-
```typescript
|
|
317
|
-
// CRITICAL GOTCHA #1: rejected[].reason is already WorkflowError
|
|
318
|
-
// Each failing workflow has its error wrapped by @Step decorator
|
|
319
|
-
// No need to create new WorkflowError objects
|
|
320
|
-
// The error object already contains: message, original, workflowId, stack, state, logs
|
|
321
|
-
// BAD: const errors = rejected.map(r => createWorkflowError(r.reason));
|
|
322
|
-
// GOOD: const errors = rejected.map(r => r.reason as WorkflowError);
|
|
323
|
-
|
|
324
|
-
// CRITICAL GOTCHA #2: Error events already emitted by @Step decorator
|
|
325
|
-
// src/decorators/step.ts:126-130 emits error events for each failing workflow
|
|
326
|
-
// DO NOT emit error events for individual failures in @Task decorator
|
|
327
|
-
// Only emit a SINGLE error event with the merged error when errorMergeStrategy is enabled
|
|
328
|
-
// When errorMergeStrategy is NOT enabled, no error event here (individual events already emitted)
|
|
329
|
-
|
|
330
|
-
// CRITICAL GOTCHA #3: combine() function signature
|
|
331
|
-
// combine?(errors: WorkflowError[]): WorkflowError
|
|
332
|
-
// Takes array of WorkflowError, returns single WorkflowError
|
|
333
|
-
// User-provided function must return valid WorkflowError object
|
|
334
|
-
// If user returns something invalid, it will fail at emitEvent or throw
|
|
335
|
-
|
|
336
|
-
// CRITICAL GOTCHA #4: maxMergeDepth is NOT used in this task
|
|
337
|
-
// The maxMergeDepth option exists in ErrorMergeStrategy interface
|
|
338
|
-
// It's intended for future recursive error merging (nested concurrent tasks)
|
|
339
|
-
// This task does NOT implement recursive merging - just flat aggregation
|
|
340
|
-
// Ignore maxMergeDepth for now, will be used in future enhancements
|
|
341
|
-
|
|
342
|
-
// CRITICAL GOTCHA #5: Backward compatibility is MANDATORY
|
|
343
|
-
// When errorMergeStrategy is undefined or enabled is false:
|
|
344
|
-
// - MUST throw rejected[0].reason (first error)
|
|
345
|
-
// - MUST NOT emit error event (already emitted by @Step)
|
|
346
|
-
// When errorMergeStrategy.enabled is true:
|
|
347
|
-
// - MUST throw merged error (not first error)
|
|
348
|
-
// - MUST emit error event with merged error
|
|
349
|
-
// Tests will verify both behaviors work correctly
|
|
350
|
-
|
|
351
|
-
// CRITICAL GOTCHA #6: Type safety for WorkflowError
|
|
352
|
-
// rejected[0].reason is technically `unknown`, not WorkflowError
|
|
353
|
-
// Must cast to WorkflowError: `as WorkflowError`
|
|
354
|
-
// TypeScript won't automatically narrow based on our knowledge of @Step behavior
|
|
355
|
-
|
|
356
|
-
// CRITICAL GOTCHA #7: Runnable workflow context
|
|
357
|
-
// rejected array contains results, not workflow objects
|
|
358
|
-
// To get workflow info (id, name), access via runnable array index
|
|
359
|
-
// Each rejected[i] corresponds to runnable[i]
|
|
360
|
-
// Not needed for default merger (WorkflowError already has workflowId)
|
|
361
|
-
|
|
362
|
-
// CRITICAL GOTCHA #8: Event emission timing
|
|
363
|
-
// Emit error event BEFORE throwing the error
|
|
364
|
-
// This matches @Step decorator pattern (emit then throw)
|
|
365
|
-
// Observers see the error before it propagates up the call stack
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
## Implementation Blueprint
|
|
369
|
-
|
|
370
|
-
### Data Models and Structure
|
|
371
|
-
|
|
372
|
-
**No new data models for this task** - using existing types:
|
|
373
|
-
|
|
374
|
-
* `WorkflowError` from `src/types/error.ts` (error structure)
|
|
375
|
-
* `ErrorMergeStrategy` from `src/types/error-strategy.ts` (configuration)
|
|
376
|
-
* `WorkflowEvent` from `src/types/events.ts` (error event structure)
|
|
377
|
-
|
|
378
|
-
**Inline Default Error Merger** (to be extracted to utils in P1.M2.T2.S3):
|
|
379
|
-
|
|
380
|
-
```typescript
|
|
381
|
-
// Inline default error merger (will be extracted to src/utils/error-merger.ts in P1.M2.T2.S3)
|
|
382
|
-
// This function creates a merged WorkflowError containing information from all errors
|
|
383
|
-
const defaultErrorMerger = (
|
|
384
|
-
errors: WorkflowError[],
|
|
385
|
-
taskName: string,
|
|
386
|
-
parentWorkflowId: string,
|
|
387
|
-
totalChildren: number
|
|
388
|
-
): WorkflowError => {
|
|
389
|
-
// Create merged error message
|
|
390
|
-
const message = `${errors.length} of ${totalChildren} concurrent child workflows failed in task '${taskName}'`;
|
|
391
|
-
|
|
392
|
-
// Get all unique workflow IDs that failed
|
|
393
|
-
const failedWorkflowIds = [...new Set(errors.map((e) => e.workflowId))];
|
|
394
|
-
|
|
395
|
-
// Aggregate all logs
|
|
396
|
-
const allLogs = errors.flatMap((e) => e.logs);
|
|
397
|
-
|
|
398
|
-
// Create merged WorkflowError
|
|
399
|
-
const mergedError: WorkflowError = {
|
|
400
|
-
message,
|
|
401
|
-
original: {
|
|
402
|
-
name: 'WorkflowAggregateError',
|
|
403
|
-
message,
|
|
404
|
-
errors,
|
|
405
|
-
totalChildren,
|
|
406
|
-
failedChildren: errors.length,
|
|
407
|
-
failedWorkflowIds,
|
|
408
|
-
} as unknown,
|
|
409
|
-
workflowId: parentWorkflowId,
|
|
410
|
-
stack: errors[0]?.stack, // Use first error's stack trace
|
|
411
|
-
state: errors[0]?.state || {} as SerializedWorkflowState, // Use first error's state
|
|
412
|
-
logs: allLogs,
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
return mergedError;
|
|
416
|
-
};
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
### Implementation Tasks (ordered by dependencies)
|
|
420
|
-
|
|
421
|
-
```yaml
|
|
422
|
-
Task 1: MODIFY src/decorators/task.ts - Add type imports for error aggregation
|
|
423
|
-
- ADD: No new imports needed - WorkflowError already in type imports
|
|
424
|
-
- VERIFY: TaskOptions import includes errorMergeStrategy field
|
|
425
|
-
- DEPENDENCIES: None
|
|
426
|
-
|
|
427
|
-
Task 2: MODIFY src/decorators/task.ts - Add inline default error merger function
|
|
428
|
-
- ADD: defaultErrorMerger function before Task decorator (after line 16)
|
|
429
|
-
- PATTERN: Follow inline helper pattern (similar to type guards)
|
|
430
|
-
- PARAMETERS: (errors: WorkflowError[], taskName: string, workflowId: string, totalChildren: number)
|
|
431
|
-
- RETURN: WorkflowError (merged error with aggregated information)
|
|
432
|
-
- IMPLEMENTATION: See "Inline Default Error Merger" section above
|
|
433
|
-
- DEPENDENCIES: None
|
|
434
|
-
|
|
435
|
-
Task 3: MODIFY src/decorators/task.ts - Replace error throwing logic (lines 118-120)
|
|
436
|
-
- CURRENT CODE:
|
|
437
|
-
if (rejected.length > 0) {
|
|
438
|
-
throw rejected[0].reason;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
- REPLACE WITH:
|
|
442
|
-
if (rejected.length > 0) {
|
|
443
|
-
// Check if error merge strategy is enabled
|
|
444
|
-
if (opts.errorMergeStrategy?.enabled) {
|
|
445
|
-
// Extract WorkflowError objects from rejected promises
|
|
446
|
-
const errors = rejected.map((r) => r.reason as WorkflowError);
|
|
447
|
-
|
|
448
|
-
// Merge errors using custom combine() or default merger
|
|
449
|
-
const mergedError = opts.errorMergeStrategy?.combine
|
|
450
|
-
? opts.errorMergeStrategy.combine(errors)
|
|
451
|
-
: defaultErrorMerger(errors, taskName, wf.id, runnable.length);
|
|
452
|
-
|
|
453
|
-
// Emit error event with merged error
|
|
454
|
-
wf.emitEvent({
|
|
455
|
-
type: 'error',
|
|
456
|
-
node: wf.node,
|
|
457
|
-
error: mergedError,
|
|
458
|
-
});
|
|
459
|
-
|
|
460
|
-
// Throw merged error
|
|
461
|
-
throw mergedError;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
// Backward compatibility: throw first error
|
|
465
|
-
throw rejected[0].reason;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
- DEPENDENCIES: Task 2
|
|
469
|
-
|
|
470
|
-
Task 4: VERIFY TypeScript compilation
|
|
471
|
-
- RUN: npx tsc --noEmit
|
|
472
|
-
- EXPECTED: No type errors
|
|
473
|
-
- VERIFY: WorkflowError type is available
|
|
474
|
-
- VERIFY: opts.errorMergeStrategy type is correct
|
|
475
|
-
- DEPENDENCIES: Task 3
|
|
476
|
-
|
|
477
|
-
Task 5: RUN existing tests
|
|
478
|
-
- RUN: npm test
|
|
479
|
-
- VERIFY: All existing tests pass (backward compatibility)
|
|
480
|
-
- VERIFY: No behavior changes when errorMergeStrategy not provided
|
|
481
|
-
- DEPENDENCIES: Task 4
|
|
482
|
-
|
|
483
|
-
Task 6: MANUAL TEST - Verify error aggregation works
|
|
484
|
-
- CREATE: Test workflow with errorMergeStrategy enabled
|
|
485
|
-
- VERIFY: Multiple errors are aggregated
|
|
486
|
-
- VERIFY: Merged error contains all error information
|
|
487
|
-
- VERIFY: Error event is emitted with merged error
|
|
488
|
-
- DEPENDENCIES: Task 5
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
### Implementation Patterns & Key Details
|
|
492
|
-
|
|
493
|
-
```typescript
|
|
494
|
-
// ============================================
|
|
495
|
-
// PATTERN 1: Error Merge Strategy Check
|
|
496
|
-
// Location: src/decorators/task.ts lines 118-120
|
|
497
|
-
// ============================================
|
|
498
|
-
|
|
499
|
-
// BEFORE (current):
|
|
500
|
-
if (rejected.length > 0) {
|
|
501
|
-
throw rejected[0].reason;
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
// AFTER (target):
|
|
505
|
-
if (rejected.length > 0) {
|
|
506
|
-
// Check if error merge strategy is enabled
|
|
507
|
-
if (opts.errorMergeStrategy?.enabled) {
|
|
508
|
-
// Error aggregation logic...
|
|
509
|
-
// Emit error event with merged error
|
|
510
|
-
// Throw merged error
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// Backward compatibility: throw first error
|
|
514
|
-
throw rejected[0].reason;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
// KEY INSIGHTS:
|
|
518
|
-
// - Optional chaining (?.) safely checks if errorMergeStrategy exists
|
|
519
|
-
// - Check enabled property before aggregating
|
|
520
|
-
// - Fall through to original behavior if not enabled
|
|
521
|
-
// - Maintains exact backward compatibility
|
|
522
|
-
|
|
523
|
-
// ============================================
|
|
524
|
-
// PATTERN 2: Extract WorkflowError Array
|
|
525
|
-
// Location: src/decorators/task.ts inside error merge strategy block
|
|
526
|
-
// ============================================
|
|
527
|
-
|
|
528
|
-
// Extract WorkflowError objects from rejected promises
|
|
529
|
-
const errors = rejected.map((r) => r.reason as WorkflowError);
|
|
530
|
-
|
|
531
|
-
// KEY INSIGHTS:
|
|
532
|
-
// - rejected[].reason is technically `unknown` (Promise rejection type)
|
|
533
|
-
// - Cast to WorkflowError because we know @Step decorator wraps errors
|
|
534
|
-
// - Map operation creates array of WorkflowError
|
|
535
|
-
// - Array is passed to combine() function or default merger
|
|
536
|
-
// - Type assertion is safe because of Groundswell's error wrapping pattern
|
|
537
|
-
|
|
538
|
-
// ============================================
|
|
539
|
-
// PATTERN 3: Custom combine() vs Default Merger
|
|
540
|
-
// Location: src/decorators/task.ts inside error merge strategy block
|
|
541
|
-
// ============================================
|
|
542
|
-
|
|
543
|
-
// Merge errors using custom combine() or default merger
|
|
544
|
-
const mergedError = opts.errorMergeStrategy?.combine
|
|
545
|
-
? opts.errorMergeStrategy.combine(errors)
|
|
546
|
-
: defaultErrorMerger(errors, taskName, wf.id, runnable.length);
|
|
547
|
-
|
|
548
|
-
// KEY INSIGHTS:
|
|
549
|
-
// - Ternary operator chooses between custom and default merger
|
|
550
|
-
// - opts.errorMergeStrategy?.combine is optional function
|
|
551
|
-
// - If provided, call it with errors array
|
|
552
|
-
// - If not provided, use inline default error merger
|
|
553
|
-
// - Both return WorkflowError object
|
|
554
|
-
// - User has full control over error merging when providing combine()
|
|
555
|
-
|
|
556
|
-
// ============================================
|
|
557
|
-
// PATTERN 4: Default Error Merger Implementation
|
|
558
|
-
// Location: src/decorators/task.ts (inline function before Task decorator)
|
|
559
|
-
// ============================================
|
|
560
|
-
|
|
561
|
-
const defaultErrorMerger = (
|
|
562
|
-
errors: WorkflowError[],
|
|
563
|
-
taskName: string,
|
|
564
|
-
parentWorkflowId: string,
|
|
565
|
-
totalChildren: number
|
|
566
|
-
): WorkflowError => {
|
|
567
|
-
// Create merged error message
|
|
568
|
-
const message = `${errors.length} of ${totalChildren} concurrent child workflows failed in task '${taskName}'`;
|
|
569
|
-
|
|
570
|
-
// Get all unique workflow IDs that failed
|
|
571
|
-
const failedWorkflowIds = [...new Set(errors.map((e) => e.workflowId))];
|
|
572
|
-
|
|
573
|
-
// Aggregate all logs
|
|
574
|
-
const allLogs = errors.flatMap((e) => e.logs);
|
|
575
|
-
|
|
576
|
-
// Create merged WorkflowError
|
|
577
|
-
const mergedError: WorkflowError = {
|
|
578
|
-
message,
|
|
579
|
-
original: {
|
|
580
|
-
name: 'WorkflowAggregateError',
|
|
581
|
-
message,
|
|
582
|
-
errors,
|
|
583
|
-
totalChildren,
|
|
584
|
-
failedChildren: errors.length,
|
|
585
|
-
failedWorkflowIds,
|
|
586
|
-
} as unknown,
|
|
587
|
-
workflowId: parentWorkflowId,
|
|
588
|
-
stack: errors[0]?.stack,
|
|
589
|
-
state: errors[0]?.state || {} as SerializedWorkflowState,
|
|
590
|
-
logs: allLogs,
|
|
591
|
-
};
|
|
592
|
-
|
|
593
|
-
return mergedError;
|
|
594
|
-
};
|
|
595
|
-
|
|
596
|
-
// KEY INSIGHTS:
|
|
597
|
-
// - Message is descriptive (counts, task name, parent workflow)
|
|
598
|
-
// - Aggregates all logs from all errors (flatMap)
|
|
599
|
-
// - Stores aggregated metadata in original field (as unknown for flexibility)
|
|
600
|
-
// - Uses first error's stack trace (representative stack)
|
|
601
|
-
// - Uses first error's state (representative state)
|
|
602
|
-
// - Returns valid WorkflowError object (can be emitted in error event)
|
|
603
|
-
|
|
604
|
-
// ============================================
|
|
605
|
-
// PATTERN 5: Error Event Emission with Merged Error
|
|
606
|
-
// Location: src/decorators/task.ts inside error merge strategy block
|
|
607
|
-
// ============================================
|
|
608
|
-
|
|
609
|
-
// Emit error event with merged error
|
|
610
|
-
wf.emitEvent({
|
|
611
|
-
type: 'error',
|
|
612
|
-
node: wf.node,
|
|
613
|
-
error: mergedError,
|
|
614
|
-
});
|
|
615
|
-
|
|
616
|
-
// KEY INSIGHTS:
|
|
617
|
-
// - Emit BEFORE throwing (matches @Step decorator pattern)
|
|
618
|
-
// - Single error event for ALL failures (not one per failure)
|
|
619
|
-
// - Observers receive aggregated error information
|
|
620
|
-
// - Enables monitoring of aggregate failure scenarios
|
|
621
|
-
// - Only emitted when errorMergeStrategy.enabled === true
|
|
622
|
-
// - When not enabled, individual workflow error events already emitted by @Step
|
|
623
|
-
|
|
624
|
-
// ============================================
|
|
625
|
-
// PATTERN 6: Throw Merged Error
|
|
626
|
-
// Location: src/decorators/task.ts after error event emission
|
|
627
|
-
// ============================================
|
|
628
|
-
|
|
629
|
-
// Throw merged error
|
|
630
|
-
throw mergedError;
|
|
631
|
-
|
|
632
|
-
// KEY INSIGHTS:
|
|
633
|
-
// - Throw AFTER emitting event (observers see it before propagation)
|
|
634
|
-
// - Thrown error is WorkflowError (same type as individual errors)
|
|
635
|
-
// - Caller can check if it's an aggregate by inspecting original field
|
|
636
|
-
// - Maintains error type consistency across the codebase
|
|
637
|
-
// - Stack trace will point to this location (expected behavior)
|
|
638
|
-
|
|
639
|
-
// ============================================
|
|
640
|
-
// PATTERN 7: Backward Compatibility Fallthrough
|
|
641
|
-
// Location: src/decorators/task.ts after error merge strategy block
|
|
642
|
-
// ============================================
|
|
643
|
-
|
|
644
|
-
// Backward compatibility: throw first error
|
|
645
|
-
throw rejected[0].reason;
|
|
646
|
-
|
|
647
|
-
// KEY INSIGHTS:
|
|
648
|
-
// - This code runs when errorMergeStrategy is undefined or enabled === false
|
|
649
|
-
// - Maintains EXACT same behavior as before this change
|
|
650
|
-
// - First error is thrown (fail-fast behavior)
|
|
651
|
-
// - No error event emitted here (individual events already emitted by @Step)
|
|
652
|
-
// - Existing tests verify this behavior is preserved
|
|
653
|
-
```
|
|
654
|
-
|
|
655
|
-
### Integration Points
|
|
656
|
-
|
|
657
|
-
```yaml
|
|
658
|
-
TASK_DECORATOR:
|
|
659
|
-
- modify: src/decorators/task.ts
|
|
660
|
-
lines: 118-120 (error throwing logic)
|
|
661
|
-
add: errorMergeStrategy check, error aggregation, merged error event
|
|
662
|
-
|
|
663
|
-
- add: inline defaultErrorMerger function (before Task decorator, after line 16)
|
|
664
|
-
|
|
665
|
-
TASK_OPTIONS:
|
|
666
|
-
- reference: src/types/decorators.ts
|
|
667
|
-
field: errorMergeStrategy?: ErrorMergeStrategy
|
|
668
|
-
note: Already added in P1.M2.T2.S1
|
|
669
|
-
|
|
670
|
-
- access: opts.errorMergeStrategy?.enabled
|
|
671
|
-
- access: opts.errorMergeStrategy?.combine
|
|
672
|
-
|
|
673
|
-
ERROR_TYPES:
|
|
674
|
-
- reference: src/types/error.ts
|
|
675
|
-
interface: WorkflowError
|
|
676
|
-
fields: message, original, workflowId, stack, state, logs
|
|
677
|
-
|
|
678
|
-
- cast: rejected[].reason as WorkflowError
|
|
679
|
-
- return: WorkflowError from combine() and defaultErrorMerger()
|
|
680
|
-
|
|
681
|
-
EVENT_SYSTEM:
|
|
682
|
-
- emit: wf.emitEvent({ type: 'error', node: wf.node, error: mergedError })
|
|
683
|
-
- note: Only when errorMergeStrategy.enabled === true
|
|
684
|
-
- note: Single event for all failures (not per-failure)
|
|
685
|
-
|
|
686
|
-
FUTURE_INTEGRATIONS (P1.M2.T2.S3):
|
|
687
|
-
- extract: defaultErrorMerger to src/utils/error-merger.ts
|
|
688
|
-
- add: more sophisticated error aggregation patterns
|
|
689
|
-
- add: pretty printing and statistics generation
|
|
690
|
-
|
|
691
|
-
FUTURE_INTEGRATIONS (P1.M2.T2.S4):
|
|
692
|
-
- add: comprehensive tests for error aggregation
|
|
693
|
-
- add: tests for custom combine() function
|
|
694
|
-
- add: tests for default error merger
|
|
695
|
-
- add: tests for backward compatibility
|
|
696
|
-
```
|
|
697
|
-
|
|
698
|
-
## Validation Loop
|
|
699
|
-
|
|
700
|
-
### Level 1: Syntax & Style (Immediate Feedback)
|
|
701
|
-
|
|
702
|
-
```bash
|
|
703
|
-
# After modifying src/decorators/task.ts, run these checks
|
|
704
|
-
|
|
705
|
-
# TypeScript type checking
|
|
706
|
-
npx tsc --noEmit
|
|
707
|
-
|
|
708
|
-
# Expected: Zero type errors
|
|
709
|
-
# Common errors to fix:
|
|
710
|
-
# - "Property 'errorMergeStrategy' does not exist" → Check TaskOptions import
|
|
711
|
-
# - "Cannot cast to WorkflowError" → Check error type casting
|
|
712
|
-
# - "Property 'combine' does not exist" → Check optional chaining
|
|
713
|
-
|
|
714
|
-
# If available, run linter
|
|
715
|
-
npm run lint 2>/dev/null || echo "No linter configured"
|
|
716
|
-
```
|
|
717
|
-
|
|
718
|
-
### Level 2: Unit Tests (Component Validation)
|
|
719
|
-
|
|
720
|
-
```bash
|
|
721
|
-
# Run all existing tests to verify backward compatibility
|
|
722
|
-
npm test
|
|
723
|
-
|
|
724
|
-
# Run specific concurrent execution tests
|
|
725
|
-
npm test -- src/__tests__/adversarial/concurrent-task-failures.test.ts
|
|
726
|
-
npm test -- src/__tests__/adversarial/edge-case.test.ts
|
|
727
|
-
|
|
728
|
-
# Expected: All existing tests pass without modification
|
|
729
|
-
# If tests fail, debug - should maintain exact backward compatibility
|
|
730
|
-
```
|
|
731
|
-
|
|
732
|
-
### Level 3: Integration Testing (System Validation)
|
|
733
|
-
|
|
734
|
-
```bash
|
|
735
|
-
# Create manual test to verify error aggregation
|
|
736
|
-
cat > /tmp/test_error_merge.js << 'EOF'
|
|
737
|
-
// Manual test for error merge strategy
|
|
738
|
-
import { Workflow, Task, Step } from './src/index.js';
|
|
739
|
-
|
|
740
|
-
class FailingWorkflow extends Workflow {
|
|
741
|
-
constructor(id: string, parent?: Workflow) {
|
|
742
|
-
super(id, parent);
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
@Step()
|
|
746
|
-
async run() {
|
|
747
|
-
throw new Error(`Failure in ${this.id}`);
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
class ParentWorkflow extends Workflow {
|
|
752
|
-
constructor(id: string, useMergeStrategy: boolean = true) {
|
|
753
|
-
super(id);
|
|
754
|
-
this.useMergeStrategy = useMergeStrategy;
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
private useMergeStrategy: boolean;
|
|
758
|
-
|
|
759
|
-
@Task({
|
|
760
|
-
concurrent: true,
|
|
761
|
-
errorMergeStrategy: this.useMergeStrategy ? {
|
|
762
|
-
enabled: true,
|
|
763
|
-
// Custom combine function
|
|
764
|
-
combine: (errors) => ({
|
|
765
|
-
message: `Custom merge: ${errors.length} workflows failed`,
|
|
766
|
-
original: errors,
|
|
767
|
-
workflowId: 'parent',
|
|
768
|
-
logs: errors.flatMap(e => e.logs),
|
|
769
|
-
}),
|
|
770
|
-
} : undefined,
|
|
771
|
-
})
|
|
772
|
-
async spawnFailingChildren() {
|
|
773
|
-
return [
|
|
774
|
-
new FailingWorkflow('child1', this),
|
|
775
|
-
new FailingWorkflow('child2', this),
|
|
776
|
-
new FailingWorkflow('child3', this),
|
|
777
|
-
];
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
async run() {
|
|
781
|
-
return this.spawnFailingChildren();
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
async function test() {
|
|
786
|
-
console.log('=== Test 1: With Error Merge Strategy ===');
|
|
787
|
-
const parent1 = new ParentWorkflow('parent1', true);
|
|
788
|
-
try {
|
|
789
|
-
await parent1.run();
|
|
790
|
-
} catch (error) {
|
|
791
|
-
console.log('Caught merged error:', error.message);
|
|
792
|
-
console.log('Original field contains errors array:', Array.isArray(error.original));
|
|
793
|
-
console.log('Number of errors:', error.original?.length || 0);
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
console.log('\n=== Test 2: Without Error Merge Strategy (Backward Compat) ===');
|
|
797
|
-
const parent2 = new ParentWorkflow('parent2', false);
|
|
798
|
-
try {
|
|
799
|
-
await parent2.run();
|
|
800
|
-
} catch (error) {
|
|
801
|
-
console.log('Caught first error:', error.message);
|
|
802
|
-
console.log('Is WorkflowError:', 'workflowId' in error);
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
test();
|
|
807
|
-
EOF
|
|
808
|
-
|
|
809
|
-
node /tmp/test_error_merge.js
|
|
810
|
-
|
|
811
|
-
# Expected output:
|
|
812
|
-
# Test 1: Shows custom merged error with all 3 errors
|
|
813
|
-
# Test 2: Shows first error only (backward compatible)
|
|
814
|
-
|
|
815
|
-
# Clean up
|
|
816
|
-
rm /tmp/test_error_merge.js
|
|
817
|
-
```
|
|
818
|
-
|
|
819
|
-
### Level 4: Domain-Specific Validation
|
|
820
|
-
|
|
821
|
-
```bash
|
|
822
|
-
# Test default error merger (without custom combine)
|
|
823
|
-
cat > /tmp/test_default_merger.js << 'EOF'
|
|
824
|
-
import { Workflow, Task, Step } from './src/index.js';
|
|
825
|
-
|
|
826
|
-
class FailingWorkflow extends Workflow {
|
|
827
|
-
@Step()
|
|
828
|
-
async run() {
|
|
829
|
-
throw new Error(`Failed in ${this.id}`);
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
class ParentWorkflow extends Workflow {
|
|
834
|
-
@Task({
|
|
835
|
-
concurrent: true,
|
|
836
|
-
errorMergeStrategy: { enabled: true }, // No combine function - use default
|
|
837
|
-
})
|
|
838
|
-
async spawnChildren() {
|
|
839
|
-
return [
|
|
840
|
-
new FailingWorkflow('child1', this),
|
|
841
|
-
new FailingWorkflow('child2', this),
|
|
842
|
-
];
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
async run() {
|
|
846
|
-
return this.spawnChildren();
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
async function test() {
|
|
851
|
-
const parent = new ParentWorkflow('parent');
|
|
852
|
-
try {
|
|
853
|
-
await parent.run();
|
|
854
|
-
} catch (error) {
|
|
855
|
-
console.log('Default merged error message:', error.message);
|
|
856
|
-
console.log('Original field:', JSON.stringify(error.original, null, 2));
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
test();
|
|
861
|
-
EOF
|
|
862
|
-
|
|
863
|
-
node /tmp/test_default_merger.js
|
|
864
|
-
|
|
865
|
-
# Expected: Default merger creates proper WorkflowError with:
|
|
866
|
-
# - Descriptive message with counts
|
|
867
|
-
# - Original field containing errors array
|
|
868
|
-
# - All logs aggregated
|
|
869
|
-
```
|
|
870
|
-
|
|
871
|
-
## Final Validation Checklist
|
|
872
|
-
|
|
873
|
-
### Technical Validation
|
|
874
|
-
|
|
875
|
-
* [ ] TypeScript compilation succeeds: `npx tsc --noEmit`
|
|
876
|
-
* [ ] defaultErrorMerger function returns valid WorkflowError
|
|
877
|
-
* [ ] opts.errorMergeStrategy?.enabled check uses optional chaining
|
|
878
|
-
* [ ] errors array correctly cast to WorkflowError[]
|
|
879
|
-
* [ ] Custom combine() called when provided
|
|
880
|
-
* [ ] Default merger used when combine() not provided
|
|
881
|
-
* [ ] Error event emitted with merged error
|
|
882
|
-
* [ ] Merged error thrown instead of first error when enabled
|
|
883
|
-
|
|
884
|
-
### Backward Compatibility Validation
|
|
885
|
-
|
|
886
|
-
* [ ] When errorMergeStrategy is undefined: first error thrown
|
|
887
|
-
* [ ] When errorMergeStrategy.enabled is false: first error thrown
|
|
888
|
-
* [ ] When errorMergeStrategy.enabled is true: merged error thrown
|
|
889
|
-
* [ ] No error event emitted when merge strategy not enabled
|
|
890
|
-
* [ ] All existing tests pass without modification
|
|
891
|
-
|
|
892
|
-
### Feature Validation
|
|
893
|
-
|
|
894
|
-
* [ ] Multiple concurrent workflow errors are aggregated
|
|
895
|
-
* [ ] Custom combine() function receives WorkflowError array
|
|
896
|
-
* [ ] Custom combine() return value is used as merged error
|
|
897
|
-
* [ ] Default merger creates WorkflowError with aggregated information
|
|
898
|
-
* [ ] Merged error message includes failure count
|
|
899
|
-
* [ ] All logs from all errors are aggregated
|
|
900
|
-
* [ ] Error event contains merged error
|
|
901
|
-
|
|
902
|
-
### Code Quality Validation
|
|
903
|
-
|
|
904
|
-
* [ ] Follows existing code patterns (indentation, naming, style)
|
|
905
|
-
* [ ] No console.log or debug statements left in
|
|
906
|
-
* [ ] Error handling is specific (throwing exact error, not new wrapper)
|
|
907
|
-
* [ ] Type safety maintained (all casts are safe)
|
|
908
|
-
* [ ] Comments added for clarity (optional chaining, backward compatibility)
|
|
909
|
-
|
|
910
|
-
### Documentation & Deployment
|
|
911
|
-
|
|
912
|
-
* [ ] Code is self-documenting with clear variable names
|
|
913
|
-
* [ ] Inline comments explain error merge strategy logic
|
|
914
|
-
* [ ] Backward compatibility is clearly documented in comments
|
|
915
|
-
* [ ] No breaking changes to public API
|
|
916
|
-
|
|
917
|
-
## Anti-Patterns to Avoid
|
|
918
|
-
|
|
919
|
-
* ❌ **Don't create new WorkflowError objects** - rejected[].reason is already WorkflowError
|
|
920
|
-
* ❌ **Don't emit error events for individual failures** - @Step decorator already does this
|
|
921
|
-
* ❌ **Don't throw error without emitting event** - Must emit before throw (pattern consistency)
|
|
922
|
-
* ❌ **Don't ignore combine() return value** - User's custom function must be used when provided
|
|
923
|
-
* ❌ **Don't assume combine() returns WorkflowError** - Trust user's implementation, TypeScript validates
|
|
924
|
-
* ❌ **Don't aggregate when errorMergeStrategy is undefined** - Must check both exists AND enabled
|
|
925
|
-
* ❌ **Don't break backward compatibility** - Default behavior must be unchanged
|
|
926
|
-
* ❌ **Don't use maxMergeDepth in this task** - Future enhancement, ignore for now
|
|
927
|
-
* ❌ **Don't add try-catch around combine()** - Let user errors propagate naturally
|
|
928
|
-
* ❌ **Don't create new files** - This task only modifies task.ts (P1.M2.T2.S3 adds utility file)
|
|
929
|
-
|
|
930
|
-
## Success Metrics
|
|
931
|
-
|
|
932
|
-
**Confidence Score**: 9/10 for one-pass implementation success
|
|
933
|
-
|
|
934
|
-
**Definition of Done**:
|
|
935
|
-
|
|
936
|
-
1. src/decorators/task.ts implements error aggregation when errorMergeStrategy.enabled === true
|
|
937
|
-
2. Custom combine() function is called when provided
|
|
938
|
-
3. Default error merger is used when combine() is not provided
|
|
939
|
-
4. Merged error is thrown instead of first error when enabled
|
|
940
|
-
5. Error event is emitted with merged error
|
|
941
|
-
6. Backward compatibility maintained (first error thrown when not enabled)
|
|
942
|
-
7. All existing tests pass
|
|
943
|
-
8. Zero TypeScript type errors
|
|
944
|
-
|
|
945
|
-
**Validation**: The implementation enables configurable error aggregation for concurrent workflows while maintaining complete backward compatibility.
|
|
946
|
-
|
|
947
|
-
---
|
|
948
|
-
|
|
949
|
-
## Appendix: Complete Code Change Reference
|
|
950
|
-
|
|
951
|
-
### Exact Change Required (src/decorators/task.ts)
|
|
952
|
-
|
|
953
|
-
**Add after line 16 (before Task decorator):**
|
|
954
|
-
|
|
955
|
-
```typescript
|
|
956
|
-
// Default error merger for concurrent workflow failures
|
|
957
|
-
// This will be extracted to src/utils/error-merger.ts in P1.M2.T2.S3
|
|
958
|
-
const defaultErrorMerger = (
|
|
959
|
-
errors: WorkflowError[],
|
|
960
|
-
taskName: string,
|
|
961
|
-
parentWorkflowId: string,
|
|
962
|
-
totalChildren: number
|
|
963
|
-
): WorkflowError => {
|
|
964
|
-
// Create merged error message
|
|
965
|
-
const message = `${errors.length} of ${totalChildren} concurrent child workflows failed in task '${taskName}'`;
|
|
966
|
-
|
|
967
|
-
// Get all unique workflow IDs that failed
|
|
968
|
-
const failedWorkflowIds = [...new Set(errors.map((e) => e.workflowId))];
|
|
969
|
-
|
|
970
|
-
// Aggregate all logs
|
|
971
|
-
const allLogs = errors.flatMap((e) => e.logs);
|
|
972
|
-
|
|
973
|
-
// Create merged WorkflowError
|
|
974
|
-
const mergedError: WorkflowError = {
|
|
975
|
-
message,
|
|
976
|
-
original: {
|
|
977
|
-
name: 'WorkflowAggregateError',
|
|
978
|
-
message,
|
|
979
|
-
errors,
|
|
980
|
-
totalChildren,
|
|
981
|
-
failedChildren: errors.length,
|
|
982
|
-
failedWorkflowIds,
|
|
983
|
-
} as unknown,
|
|
984
|
-
workflowId: parentWorkflowId,
|
|
985
|
-
stack: errors[0]?.stack,
|
|
986
|
-
state: errors[0]?.state || {} as SerializedWorkflowState,
|
|
987
|
-
logs: allLogs,
|
|
988
|
-
};
|
|
989
|
-
|
|
990
|
-
return mergedError;
|
|
991
|
-
};
|
|
992
|
-
```
|
|
993
|
-
|
|
994
|
-
**Replace lines 118-120:**
|
|
995
|
-
|
|
996
|
-
```typescript
|
|
997
|
-
// BEFORE:
|
|
998
|
-
if (rejected.length > 0) {
|
|
999
|
-
throw rejected[0].reason;
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
// AFTER:
|
|
1003
|
-
if (rejected.length > 0) {
|
|
1004
|
-
// Check if error merge strategy is enabled
|
|
1005
|
-
if (opts.errorMergeStrategy?.enabled) {
|
|
1006
|
-
// Extract WorkflowError objects from rejected promises
|
|
1007
|
-
const errors = rejected.map((r) => r.reason as WorkflowError);
|
|
1008
|
-
|
|
1009
|
-
// Merge errors using custom combine() or default merger
|
|
1010
|
-
const mergedError = opts.errorMergeStrategy?.combine
|
|
1011
|
-
? opts.errorMergeStrategy.combine(errors)
|
|
1012
|
-
: defaultErrorMerger(errors, taskName, wf.id, runnable.length);
|
|
1013
|
-
|
|
1014
|
-
// Emit error event with merged error
|
|
1015
|
-
wf.emitEvent({
|
|
1016
|
-
type: 'error',
|
|
1017
|
-
node: wf.node,
|
|
1018
|
-
error: mergedError,
|
|
1019
|
-
});
|
|
1020
|
-
|
|
1021
|
-
// Throw merged error
|
|
1022
|
-
throw mergedError;
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
// Backward compatibility: throw first error
|
|
1026
|
-
throw rejected[0].reason;
|
|
1027
|
-
}
|
|
1028
|
-
```
|
|
1029
|
-
|
|
1030
|
-
**Diff Summary:**
|
|
1031
|
-
|
|
1032
|
-
```diff
|
|
1033
|
-
+ // Default error merger for concurrent workflow failures
|
|
1034
|
-
+ const defaultErrorMerger = (...)
|
|
1035
|
-
+
|
|
1036
|
-
if (rejected.length > 0) {
|
|
1037
|
-
+ // Check if error merge strategy is enabled
|
|
1038
|
-
+ if (opts.errorMergeStrategy?.enabled) {
|
|
1039
|
-
+ // Extract WorkflowError objects from rejected promises
|
|
1040
|
-
+ const errors = rejected.map((r) => r.reason as WorkflowError);
|
|
1041
|
-
+
|
|
1042
|
-
+ // Merge errors using custom combine() or default merger
|
|
1043
|
-
+ const mergedError = opts.errorMergeStrategy?.combine
|
|
1044
|
-
+ ? opts.errorMergeStrategy.combine(errors)
|
|
1045
|
-
+ : defaultErrorMerger(errors, taskName, wf.id, runnable.length);
|
|
1046
|
-
+
|
|
1047
|
-
+ // Emit error event with merged error
|
|
1048
|
-
+ wf.emitEvent({
|
|
1049
|
-
+ type: 'error',
|
|
1050
|
-
+ node: wf.node,
|
|
1051
|
-
+ error: mergedError,
|
|
1052
|
-
+ });
|
|
1053
|
-
+
|
|
1054
|
-
+ // Throw merged error
|
|
1055
|
-
+ throw mergedError;
|
|
1056
|
-
+ }
|
|
1057
|
-
+
|
|
1058
|
-
// Backward compatibility: throw first error
|
|
1059
|
-
throw rejected[0].reason;
|
|
1060
|
-
}
|
|
1061
|
-
```
|
|
1062
|
-
|
|
1063
|
-
---
|
|
1064
|
-
|
|
1065
|
-
**PRP Status**: ✅ Complete - Ready for Implementation
|
|
1066
|
-
**Next Task**: P1.M2.T2.S3 - Create default error merger implementation
|