groundswell 0.0.2 → 0.0.3
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/dist/__tests__/adversarial/attachChild-performance.test.d.ts +16 -0
- package/dist/__tests__/adversarial/attachChild-performance.test.d.ts.map +1 -0
- package/dist/__tests__/adversarial/attachChild-performance.test.js +187 -0
- package/dist/__tests__/adversarial/attachChild-performance.test.js.map +1 -0
- package/dist/__tests__/adversarial/circular-reference.test.d.ts +13 -0
- package/dist/__tests__/adversarial/circular-reference.test.d.ts.map +1 -0
- package/dist/__tests__/adversarial/circular-reference.test.js +92 -0
- package/dist/__tests__/adversarial/circular-reference.test.js.map +1 -0
- package/dist/__tests__/adversarial/complex-circular-reference.test.d.ts +16 -0
- package/dist/__tests__/adversarial/complex-circular-reference.test.d.ts.map +1 -0
- package/dist/__tests__/adversarial/complex-circular-reference.test.js +127 -0
- package/dist/__tests__/adversarial/complex-circular-reference.test.js.map +1 -0
- package/dist/__tests__/adversarial/concurrent-task-failures.test.d.ts +21 -0
- package/dist/__tests__/adversarial/concurrent-task-failures.test.d.ts.map +1 -0
- package/dist/__tests__/adversarial/concurrent-task-failures.test.js +667 -0
- package/dist/__tests__/adversarial/concurrent-task-failures.test.js.map +1 -0
- package/dist/__tests__/adversarial/deep-analysis.test.d.ts +6 -0
- package/dist/__tests__/adversarial/deep-analysis.test.d.ts.map +1 -0
- package/dist/__tests__/adversarial/deep-analysis.test.js +877 -0
- package/dist/__tests__/adversarial/deep-analysis.test.js.map +1 -0
- package/dist/__tests__/adversarial/deep-hierarchy-stress.test.d.ts +13 -0
- package/dist/__tests__/adversarial/deep-hierarchy-stress.test.d.ts.map +1 -0
- package/dist/__tests__/adversarial/deep-hierarchy-stress.test.js +186 -0
- package/dist/__tests__/adversarial/deep-hierarchy-stress.test.js.map +1 -0
- package/dist/__tests__/adversarial/e2e-prd-validation.test.d.ts +6 -0
- package/dist/__tests__/adversarial/e2e-prd-validation.test.d.ts.map +1 -0
- package/dist/__tests__/adversarial/e2e-prd-validation.test.js +626 -0
- package/dist/__tests__/adversarial/e2e-prd-validation.test.js.map +1 -0
- package/dist/__tests__/adversarial/edge-case.test.d.ts +6 -0
- package/dist/__tests__/adversarial/edge-case.test.d.ts.map +1 -0
- package/dist/__tests__/adversarial/edge-case.test.js +857 -0
- package/dist/__tests__/adversarial/edge-case.test.js.map +1 -0
- package/dist/__tests__/adversarial/error-merge-strategy.test.d.ts +20 -0
- package/dist/__tests__/adversarial/error-merge-strategy.test.d.ts.map +1 -0
- package/dist/__tests__/adversarial/error-merge-strategy.test.js +907 -0
- package/dist/__tests__/adversarial/error-merge-strategy.test.js.map +1 -0
- package/dist/__tests__/adversarial/incremental-performance.test.d.ts +2 -0
- package/dist/__tests__/adversarial/incremental-performance.test.d.ts.map +1 -0
- package/dist/__tests__/adversarial/incremental-performance.test.js +113 -0
- package/dist/__tests__/adversarial/incremental-performance.test.js.map +1 -0
- package/dist/__tests__/adversarial/node-map-update-benchmarks.test.d.ts +22 -0
- package/dist/__tests__/adversarial/node-map-update-benchmarks.test.d.ts.map +1 -0
- package/dist/__tests__/adversarial/node-map-update-benchmarks.test.js +383 -0
- package/dist/__tests__/adversarial/node-map-update-benchmarks.test.js.map +1 -0
- package/dist/__tests__/adversarial/observer-propagation.test.d.ts +21 -0
- package/dist/__tests__/adversarial/observer-propagation.test.d.ts.map +1 -0
- package/dist/__tests__/adversarial/observer-propagation.test.js +404 -0
- package/dist/__tests__/adversarial/observer-propagation.test.js.map +1 -0
- package/dist/__tests__/adversarial/parent-validation.test.d.ts +13 -0
- package/dist/__tests__/adversarial/parent-validation.test.d.ts.map +1 -0
- package/dist/__tests__/adversarial/parent-validation.test.js +128 -0
- package/dist/__tests__/adversarial/parent-validation.test.js.map +1 -0
- package/dist/__tests__/adversarial/prd-12-2-compliance.test.d.ts +20 -0
- package/dist/__tests__/adversarial/prd-12-2-compliance.test.d.ts.map +1 -0
- package/dist/__tests__/adversarial/prd-12-2-compliance.test.js +482 -0
- package/dist/__tests__/adversarial/prd-12-2-compliance.test.js.map +1 -0
- package/dist/__tests__/adversarial/prd-compliance.test.d.ts +6 -0
- package/dist/__tests__/adversarial/prd-compliance.test.d.ts.map +1 -0
- package/dist/__tests__/adversarial/prd-compliance.test.js +886 -0
- package/dist/__tests__/adversarial/prd-compliance.test.js.map +1 -0
- package/dist/__tests__/compatibility/backward-compatibility.test.d.ts +22 -0
- package/dist/__tests__/compatibility/backward-compatibility.test.d.ts.map +1 -0
- package/dist/__tests__/compatibility/backward-compatibility.test.js +1843 -0
- package/dist/__tests__/compatibility/backward-compatibility.test.js.map +1 -0
- package/dist/__tests__/helpers/index.d.ts +10 -0
- package/dist/__tests__/helpers/index.d.ts.map +1 -0
- package/{src/__tests__/helpers/index.ts → dist/__tests__/helpers/index.js} +2 -10
- package/dist/__tests__/helpers/index.js.map +1 -0
- package/dist/__tests__/helpers/tree-verification.d.ts +90 -0
- package/dist/__tests__/helpers/tree-verification.d.ts.map +1 -0
- package/dist/__tests__/helpers/tree-verification.js +202 -0
- package/dist/__tests__/helpers/tree-verification.js.map +1 -0
- package/dist/__tests__/integration/agent-workflow.test.d.ts +2 -0
- package/dist/__tests__/integration/agent-workflow.test.d.ts.map +1 -0
- package/dist/__tests__/integration/agent-workflow.test.js +256 -0
- package/dist/__tests__/integration/agent-workflow.test.js.map +1 -0
- package/dist/__tests__/integration/bidirectional-consistency.test.d.ts +14 -0
- package/dist/__tests__/integration/bidirectional-consistency.test.d.ts.map +1 -0
- package/dist/__tests__/integration/bidirectional-consistency.test.js +668 -0
- package/dist/__tests__/integration/bidirectional-consistency.test.js.map +1 -0
- package/dist/__tests__/integration/observer-logging.test.d.ts +2 -0
- package/dist/__tests__/integration/observer-logging.test.d.ts.map +1 -0
- package/dist/__tests__/integration/observer-logging.test.js +517 -0
- package/dist/__tests__/integration/observer-logging.test.js.map +1 -0
- package/dist/__tests__/integration/tree-mirroring.test.d.ts +2 -0
- package/dist/__tests__/integration/tree-mirroring.test.d.ts.map +1 -0
- package/dist/__tests__/integration/tree-mirroring.test.js +117 -0
- package/dist/__tests__/integration/tree-mirroring.test.js.map +1 -0
- package/dist/__tests__/integration/workflow-reparenting.test.d.ts +12 -0
- package/dist/__tests__/integration/workflow-reparenting.test.d.ts.map +1 -0
- package/dist/__tests__/integration/workflow-reparenting.test.js +239 -0
- package/dist/__tests__/integration/workflow-reparenting.test.js.map +1 -0
- package/dist/__tests__/unit/agent.test.d.ts +2 -0
- package/dist/__tests__/unit/agent.test.d.ts.map +1 -0
- package/dist/__tests__/unit/agent.test.js +143 -0
- package/dist/__tests__/unit/agent.test.js.map +1 -0
- package/dist/__tests__/unit/cache-key.test.d.ts +5 -0
- package/dist/__tests__/unit/cache-key.test.d.ts.map +1 -0
- package/dist/__tests__/unit/cache-key.test.js +145 -0
- package/dist/__tests__/unit/cache-key.test.js.map +1 -0
- package/dist/__tests__/unit/cache.test.d.ts +5 -0
- package/dist/__tests__/unit/cache.test.d.ts.map +1 -0
- package/dist/__tests__/unit/cache.test.js +132 -0
- package/dist/__tests__/unit/cache.test.js.map +1 -0
- package/dist/__tests__/unit/context.test.d.ts +2 -0
- package/dist/__tests__/unit/context.test.d.ts.map +1 -0
- package/dist/__tests__/unit/context.test.js +220 -0
- package/dist/__tests__/unit/context.test.js.map +1 -0
- package/dist/__tests__/unit/decorators.test.d.ts +2 -0
- package/dist/__tests__/unit/decorators.test.d.ts.map +1 -0
- package/dist/__tests__/unit/decorators.test.js +162 -0
- package/dist/__tests__/unit/decorators.test.js.map +1 -0
- package/dist/__tests__/unit/introspection-tools.test.d.ts +5 -0
- package/dist/__tests__/unit/introspection-tools.test.d.ts.map +1 -0
- package/dist/__tests__/unit/introspection-tools.test.js +191 -0
- package/dist/__tests__/unit/introspection-tools.test.js.map +1 -0
- package/dist/__tests__/unit/logger.test.d.ts +2 -0
- package/dist/__tests__/unit/logger.test.d.ts.map +1 -0
- package/dist/__tests__/unit/logger.test.js +241 -0
- package/dist/__tests__/unit/logger.test.js.map +1 -0
- package/dist/__tests__/unit/observable.test.d.ts +2 -0
- package/dist/__tests__/unit/observable.test.d.ts.map +1 -0
- package/dist/__tests__/unit/observable.test.js +251 -0
- package/dist/__tests__/unit/observable.test.js.map +1 -0
- package/dist/__tests__/unit/prompt.test.d.ts +2 -0
- package/dist/__tests__/unit/prompt.test.d.ts.map +1 -0
- package/dist/__tests__/unit/prompt.test.js +113 -0
- package/dist/__tests__/unit/prompt.test.js.map +1 -0
- package/dist/__tests__/unit/reflection.test.d.ts +5 -0
- package/dist/__tests__/unit/reflection.test.d.ts.map +1 -0
- package/dist/__tests__/unit/reflection.test.js +160 -0
- package/dist/__tests__/unit/reflection.test.js.map +1 -0
- package/dist/__tests__/unit/tree-debugger-incremental.test.d.ts +2 -0
- package/dist/__tests__/unit/tree-debugger-incremental.test.d.ts.map +1 -0
- package/dist/__tests__/unit/tree-debugger-incremental.test.js +136 -0
- package/dist/__tests__/unit/tree-debugger-incremental.test.js.map +1 -0
- package/dist/__tests__/unit/tree-debugger.test.d.ts +2 -0
- package/dist/__tests__/unit/tree-debugger.test.d.ts.map +1 -0
- package/dist/__tests__/unit/tree-debugger.test.js +69 -0
- package/dist/__tests__/unit/tree-debugger.test.js.map +1 -0
- package/dist/__tests__/unit/utils/workflow-error-utils.test.d.ts +2 -0
- package/dist/__tests__/unit/utils/workflow-error-utils.test.d.ts.map +1 -0
- package/dist/__tests__/unit/utils/workflow-error-utils.test.js +154 -0
- package/dist/__tests__/unit/utils/workflow-error-utils.test.js.map +1 -0
- package/dist/__tests__/unit/workflow-detachChild.test.d.ts +2 -0
- package/dist/__tests__/unit/workflow-detachChild.test.d.ts.map +1 -0
- package/dist/__tests__/unit/workflow-detachChild.test.js +76 -0
- package/dist/__tests__/unit/workflow-detachChild.test.js.map +1 -0
- package/dist/__tests__/unit/workflow-emitEvent-childDetached.test.d.ts +2 -0
- package/dist/__tests__/unit/workflow-emitEvent-childDetached.test.d.ts.map +1 -0
- package/dist/__tests__/unit/workflow-emitEvent-childDetached.test.js +122 -0
- package/dist/__tests__/unit/workflow-emitEvent-childDetached.test.js.map +1 -0
- package/dist/__tests__/unit/workflow-isDescendantOf.test.d.ts +2 -0
- package/dist/__tests__/unit/workflow-isDescendantOf.test.d.ts.map +1 -0
- package/dist/__tests__/unit/workflow-isDescendantOf.test.js +140 -0
- package/dist/__tests__/unit/workflow-isDescendantOf.test.js.map +1 -0
- package/dist/__tests__/unit/workflow.test.d.ts +2 -0
- package/dist/__tests__/unit/workflow.test.d.ts.map +1 -0
- package/dist/__tests__/unit/workflow.test.js +330 -0
- package/dist/__tests__/unit/workflow.test.js.map +1 -0
- package/dist/cache/cache-key.d.ts +66 -0
- package/dist/cache/cache-key.d.ts.map +1 -0
- package/dist/cache/cache-key.js +195 -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 +112 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +426 -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 +69 -0
- package/dist/core/mcp-handler.d.ts.map +1 -0
- package/dist/core/mcp-handler.js +143 -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 +57 -0
- package/dist/core/workflow-context.d.ts.map +1 -0
- package/dist/core/workflow-context.js +263 -0
- package/dist/core/workflow-context.js.map +1 -0
- package/dist/core/workflow.d.ts +241 -0
- package/dist/core/workflow.d.ts.map +1 -0
- package/dist/core/workflow.js +464 -0
- package/dist/core/workflow.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 +71 -0
- package/dist/debugger/tree-debugger.d.ts.map +1 -0
- package/dist/debugger/tree-debugger.js +198 -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 +110 -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/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -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 +329 -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 +66 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +6 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/decorators.d.ts +31 -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 +87 -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/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -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/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/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/workflow-context.d.ts +139 -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/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/{src/utils/index.ts → dist/utils/index.d.ts} +1 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.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/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 +5 -2
- 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/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/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/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,1103 +0,0 @@
|
|
|
1
|
-
# Vitest Testing Patterns for TypeScript Error Handling
|
|
2
|
-
|
|
3
|
-
**Research Date:** 2026-01-12
|
|
4
|
-
**Vitest Version:** 1.0.0
|
|
5
|
-
**Project:** Groundswell - Hierarchical Workflow Orchestration Engine
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Table of Contents
|
|
10
|
-
|
|
11
|
-
1. [Official Vitest Documentation Resources](#official-vitest-documentation-resources)
|
|
12
|
-
2. [Testing Error Aggregation Behavior](#testing-error-aggregation-behavior)
|
|
13
|
-
3. [Async Error Testing Best Practices](#async-error-testing-best-practices)
|
|
14
|
-
4. [Custom Error Types and Merged Errors](#custom-error-types-and-merged-errors)
|
|
15
|
-
5. [Concurrent/Parallel Execution Error Scenarios](#concurrentparallel-execution-error-scenarios)
|
|
16
|
-
6. [Common Gotchas and Pitfalls](#common-gotchas-and-pitfalls)
|
|
17
|
-
7. [Project-Specific Testing Patterns](#project-specific-testing-patterns)
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## Official Vitest Documentation Resources
|
|
22
|
-
|
|
23
|
-
### Core Documentation URLs
|
|
24
|
-
|
|
25
|
-
- **Vitest Official Website:** https://vitest.dev/
|
|
26
|
-
- **Assertions API:** https://vitest.dev/guide/assertions.html
|
|
27
|
-
- **Testing TypeScript:** https://vitest.dev/guide/testing-types.html
|
|
28
|
-
- **Async Testing:** https://vitest.dev/guide/async.html
|
|
29
|
-
- **Mocking:** https://vitest.dev/guide/mocking.html
|
|
30
|
-
- **GitHub Repository:** https://github.com/vitest-dev/vitest
|
|
31
|
-
|
|
32
|
-
### Key Documentation Sections
|
|
33
|
-
|
|
34
|
-
1. **Error Testing Assertions**
|
|
35
|
-
- `toThrow()` - Synchronous error testing
|
|
36
|
-
- `rejects.toThrow()` - Async error testing
|
|
37
|
-
- Custom matchers for error properties
|
|
38
|
-
- Error instance checking
|
|
39
|
-
|
|
40
|
-
2. **Async Testing Patterns**
|
|
41
|
-
- Promise rejection testing
|
|
42
|
-
- Async/await patterns
|
|
43
|
-
- Timeout handling
|
|
44
|
-
- Concurrent test execution
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
## Testing Error Aggregation Behavior
|
|
49
|
-
|
|
50
|
-
### Pattern 1: Testing Error Collection and Merging
|
|
51
|
-
|
|
52
|
-
**File Reference:** `/home/dustin/projects/groundswell/src/__tests__/unit/utils/workflow-error-utils.test.ts`
|
|
53
|
-
|
|
54
|
-
When testing error aggregation (combining multiple errors into one), focus on:
|
|
55
|
-
|
|
56
|
-
1. **Count Validation**
|
|
57
|
-
2. **Unique Identification**
|
|
58
|
-
3. **Context Preservation**
|
|
59
|
-
4. **Metadata Structure**
|
|
60
|
-
|
|
61
|
-
#### Code Example: Error Aggregation Testing
|
|
62
|
-
|
|
63
|
-
```typescript
|
|
64
|
-
import { describe, it, expect } from 'vitest';
|
|
65
|
-
import { mergeWorkflowErrors } from '../../../utils/workflow-error-utils.js';
|
|
66
|
-
import type { WorkflowError } from '../../../types/error.js';
|
|
67
|
-
|
|
68
|
-
describe('mergeWorkflowErrors', () => {
|
|
69
|
-
// Helper function to create mock errors
|
|
70
|
-
function createMockWorkflowError(overrides?: Partial<WorkflowError>): WorkflowError {
|
|
71
|
-
return {
|
|
72
|
-
message: 'Test error',
|
|
73
|
-
original: new Error('Original error'),
|
|
74
|
-
workflowId: 'wf-test-123',
|
|
75
|
-
stack: 'Error: Test error\n at test.ts:10:15',
|
|
76
|
-
state: { key: 'value' },
|
|
77
|
-
logs: [
|
|
78
|
-
{
|
|
79
|
-
id: 'log-1',
|
|
80
|
-
workflowId: 'wf-test-123',
|
|
81
|
-
timestamp: Date.now(),
|
|
82
|
-
level: 'error',
|
|
83
|
-
message: 'Test log message',
|
|
84
|
-
},
|
|
85
|
-
],
|
|
86
|
-
...overrides,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
it('should aggregate multiple errors with unique workflow IDs', () => {
|
|
91
|
-
const error1 = createMockWorkflowError({
|
|
92
|
-
message: 'Error 1',
|
|
93
|
-
workflowId: 'wf-1',
|
|
94
|
-
stack: 'stack 1',
|
|
95
|
-
state: { key1: 'value1' },
|
|
96
|
-
logs: [{ id: 'log-1', workflowId: 'wf-1', timestamp: 1000, level: 'error', message: 'Log 1' }],
|
|
97
|
-
});
|
|
98
|
-
const error2 = createMockWorkflowError({
|
|
99
|
-
message: 'Error 2',
|
|
100
|
-
workflowId: 'wf-2',
|
|
101
|
-
stack: 'stack 2',
|
|
102
|
-
state: { key2: 'value2' },
|
|
103
|
-
logs: [{ id: 'log-2', workflowId: 'wf-2', timestamp: 2000, level: 'error', message: 'Log 2' }],
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
const result = mergeWorkflowErrors([error1, error2], 'concurrentTask', 'parent-wf', 5);
|
|
107
|
-
|
|
108
|
-
// Validate aggregated message
|
|
109
|
-
expect(result.message).toBe("2 of 5 concurrent child workflows failed in task 'concurrentTask'");
|
|
110
|
-
expect(result.workflowId).toBe('parent-wf');
|
|
111
|
-
expect(result.stack).toBe('stack 1'); // First error's stack
|
|
112
|
-
expect(result.state).toEqual({ key1: 'value1' }); // First error's state
|
|
113
|
-
expect(result.logs).toHaveLength(2); // All logs aggregated
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it('should deduplicate workflow IDs when errors have duplicate IDs', () => {
|
|
117
|
-
const error1 = createMockWorkflowError({ workflowId: 'wf-dup' });
|
|
118
|
-
const error2 = createMockWorkflowError({ workflowId: 'wf-dup' });
|
|
119
|
-
const error3 = createMockWorkflowError({ workflowId: 'wf-unique' });
|
|
120
|
-
|
|
121
|
-
const result = mergeWorkflowErrors([error1, error2, error3], 'testTask', 'parent-wf', 4);
|
|
122
|
-
|
|
123
|
-
// Access metadata from original field
|
|
124
|
-
const metadata = result.original as {
|
|
125
|
-
failedWorkflowIds: string[];
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
expect(metadata.failedWorkflowIds).toEqual(['wf-dup', 'wf-unique']);
|
|
129
|
-
expect(metadata.failedWorkflowIds).toHaveLength(2); // Deduplicated
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
### Best Practices for Error Aggregation Testing
|
|
135
|
-
|
|
136
|
-
1. **Test Both Single and Multiple Errors**
|
|
137
|
-
```typescript
|
|
138
|
-
it('should return a single error when merging one error', () => {
|
|
139
|
-
const error = createMockWorkflowError({ workflowId: 'wf-1' });
|
|
140
|
-
const result = mergeWorkflowErrors([error], 'testTask', 'parent-wf', 1);
|
|
141
|
-
expect(result.message).toBe("1 of 1 concurrent child workflows failed in task 'testTask'");
|
|
142
|
-
});
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
2. **Test Deduplication Logic**
|
|
146
|
-
- Ensure duplicate IDs are properly handled
|
|
147
|
-
- Validate unique identifier preservation
|
|
148
|
-
|
|
149
|
-
3. **Test Array Flattening**
|
|
150
|
-
```typescript
|
|
151
|
-
it('should flatten logs arrays from all errors using flatMap', () => {
|
|
152
|
-
const error1 = createMockWorkflowError({
|
|
153
|
-
workflowId: 'wf-1',
|
|
154
|
-
logs: [
|
|
155
|
-
{ id: 'log-1', workflowId: 'wf-1', timestamp: 1000, level: 'info', message: 'Log 1.1' },
|
|
156
|
-
{ id: 'log-2', workflowId: 'wf-1', timestamp: 2000, level: 'info', message: 'Log 1.2' },
|
|
157
|
-
],
|
|
158
|
-
});
|
|
159
|
-
const error2 = createMockWorkflowError({
|
|
160
|
-
workflowId: 'wf-2',
|
|
161
|
-
logs: [
|
|
162
|
-
{ id: 'log-3', workflowId: 'wf-2', timestamp: 3000, level: 'error', message: 'Log 2.1' },
|
|
163
|
-
],
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
const result = mergeWorkflowErrors([error1, error2], 'testTask', 'parent-wf', 2);
|
|
167
|
-
expect(result.logs).toHaveLength(3);
|
|
168
|
-
});
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
4. **Test Metadata Preservation**
|
|
172
|
-
```typescript
|
|
173
|
-
it('should include metadata in original field', () => {
|
|
174
|
-
const error1 = createMockWorkflowError({ workflowId: 'wf-1' });
|
|
175
|
-
const error2 = createMockWorkflowError({ workflowId: 'wf-2' });
|
|
176
|
-
|
|
177
|
-
const result = mergeWorkflowErrors([error1, error2], 'concurrentTask', 'parent-wf', 5);
|
|
178
|
-
|
|
179
|
-
const metadata = result.original as {
|
|
180
|
-
name: string;
|
|
181
|
-
message: string;
|
|
182
|
-
errors: WorkflowError[];
|
|
183
|
-
totalChildren: number;
|
|
184
|
-
failedChildren: number;
|
|
185
|
-
failedWorkflowIds: string[];
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
expect(metadata.name).toBe('WorkflowAggregateError');
|
|
189
|
-
expect(metadata.totalChildren).toBe(5);
|
|
190
|
-
expect(metadata.failedChildren).toBe(2);
|
|
191
|
-
});
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
---
|
|
195
|
-
|
|
196
|
-
## Async Error Testing Best Practices
|
|
197
|
-
|
|
198
|
-
### Pattern 1: Using `rejects.toThrow()` for Async Errors
|
|
199
|
-
|
|
200
|
-
The most common and recommended pattern for async error testing:
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
import { describe, it, expect } from 'vitest';
|
|
204
|
-
|
|
205
|
-
describe('async error testing', () => {
|
|
206
|
-
it('should throw error', async () => {
|
|
207
|
-
await expect(asyncFunction()).rejects.toThrow();
|
|
208
|
-
await expect(asyncFunction()).rejects.toThrow('Error message');
|
|
209
|
-
await expect(asyncFunction()).rejects.toThrow(/regex/);
|
|
210
|
-
await expect(asyncFunction()).rejects.toThrow(TypeError);
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
it('should throw custom error type', async () => {
|
|
214
|
-
await expect(asyncFunction()).rejects.toThrow(CustomError);
|
|
215
|
-
});
|
|
216
|
-
});
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Pattern 2: Try-Catch with Explicit Assertions
|
|
220
|
-
|
|
221
|
-
When you need to inspect error properties:
|
|
222
|
-
|
|
223
|
-
```typescript
|
|
224
|
-
it('should preserve error context', async () => {
|
|
225
|
-
try {
|
|
226
|
-
await asyncFunction();
|
|
227
|
-
expect.fail('Expected function to throw');
|
|
228
|
-
} catch (error) {
|
|
229
|
-
expect(error).toBeInstanceOf(Error);
|
|
230
|
-
expect(error.message).toBe('specific message');
|
|
231
|
-
if (error instanceof CustomError) {
|
|
232
|
-
expect(error.code).toBe(404);
|
|
233
|
-
expect(error.metadata).toBeDefined();
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
});
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### Pattern 3: Promise.race for Timeout Detection
|
|
240
|
-
|
|
241
|
-
**File Reference:** `/home/dustin/projects/groundswell/src/__tests__/adversarial/concurrent-task-failures.test.ts`
|
|
242
|
-
|
|
243
|
-
Useful for detecting hanging promises:
|
|
244
|
-
|
|
245
|
-
```typescript
|
|
246
|
-
it('should verify all workflows complete with no hanging promises', async () => {
|
|
247
|
-
const completedWorkflows = new Set<string>();
|
|
248
|
-
|
|
249
|
-
// Setup tracking
|
|
250
|
-
children.forEach((child) => {
|
|
251
|
-
child.run().then(
|
|
252
|
-
() => completedWorkflows.add(child.id),
|
|
253
|
-
() => completedWorkflows.add(child.id)
|
|
254
|
-
);
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
// ACT: Run with timeout to detect hanging promises
|
|
258
|
-
const timeoutPromise = new Promise((_, reject) =>
|
|
259
|
-
setTimeout(() => reject(new Error('Timeout: workflows hung')), 5000)
|
|
260
|
-
);
|
|
261
|
-
|
|
262
|
-
const runPromise = parent.run();
|
|
263
|
-
|
|
264
|
-
await Promise.race([runPromise, timeoutPromise]);
|
|
265
|
-
|
|
266
|
-
// ASSERT: All workflows accounted for (no orphans)
|
|
267
|
-
expect(completedWorkflows.size).toBe(10);
|
|
268
|
-
});
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
### Pattern 4: Testing Expected Errors with try-catch
|
|
272
|
-
|
|
273
|
-
**From the project's concurrent test patterns:**
|
|
274
|
-
|
|
275
|
-
```typescript
|
|
276
|
-
class ParentWorkflow extends Workflow {
|
|
277
|
-
@Task({ concurrent: true })
|
|
278
|
-
async spawnChildren() {
|
|
279
|
-
return [
|
|
280
|
-
createChildWorkflow(this, 'Child-0', false),
|
|
281
|
-
createChildWorkflow(this, 'Child-1', true), // Will fail
|
|
282
|
-
createChildWorkflow(this, 'Child-2', false),
|
|
283
|
-
];
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
async run() {
|
|
287
|
-
try {
|
|
288
|
-
await this.spawnChildren();
|
|
289
|
-
} catch (err) {
|
|
290
|
-
// Expected - first error thrown after all complete
|
|
291
|
-
return err;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
const parent = new ParentWorkflow('Parent');
|
|
297
|
-
const thrownError = await parent.run();
|
|
298
|
-
|
|
299
|
-
// ASSERT: Error was thrown
|
|
300
|
-
expect(thrownError).toBeDefined();
|
|
301
|
-
expect((thrownError as any).message).toContain('Child-1 failed');
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
### Key Best Practices for Async Error Testing
|
|
305
|
-
|
|
306
|
-
1. **Always use `await` with `rejects.toThrow()`**
|
|
307
|
-
```typescript
|
|
308
|
-
// BAD
|
|
309
|
-
expect(asyncFunction()).rejects.toThrow();
|
|
310
|
-
|
|
311
|
-
// GOOD
|
|
312
|
-
await expect(asyncFunction()).rejects.toThrow();
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
2. **Test error messages for specificity**
|
|
316
|
-
```typescript
|
|
317
|
-
await expect(asyncFunction()).rejects.toThrow('specific error message');
|
|
318
|
-
await expect(asyncFunction()).rejects.toThrow(/error pattern/);
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
3. **Test error types when specific errors matter**
|
|
322
|
-
```typescript
|
|
323
|
-
await expect(asyncFunction()).rejects.toThrow(TypeError);
|
|
324
|
-
await expect(asyncFunction()).rejects.toThrow(CustomError);
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
4. **Use `expect.fail()` for unexpected success**
|
|
328
|
-
```typescript
|
|
329
|
-
it('should throw error', async () => {
|
|
330
|
-
try {
|
|
331
|
-
await asyncFunction();
|
|
332
|
-
expect.fail('Expected function to throw');
|
|
333
|
-
} catch (error) {
|
|
334
|
-
expect(error).toBeInstanceOf(Error);
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
5. **Handle expected errors gracefully**
|
|
340
|
-
```typescript
|
|
341
|
-
async run() {
|
|
342
|
-
try {
|
|
343
|
-
await this.spawnChildren();
|
|
344
|
-
} catch (err) {
|
|
345
|
-
// Expected - continue with validation
|
|
346
|
-
return err;
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
---
|
|
352
|
-
|
|
353
|
-
## Custom Error Types and Merged Errors
|
|
354
|
-
|
|
355
|
-
### Pattern 1: Custom Error Instance Testing
|
|
356
|
-
|
|
357
|
-
```typescript
|
|
358
|
-
class WorkflowAggregateError extends Error {
|
|
359
|
-
constructor(
|
|
360
|
-
public errors: Error[],
|
|
361
|
-
public failedWorkflowIds: string[],
|
|
362
|
-
public totalChildren: number,
|
|
363
|
-
public failedChildren: number
|
|
364
|
-
) {
|
|
365
|
-
super('Aggregate error');
|
|
366
|
-
this.name = 'WorkflowAggregateError';
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
describe('custom error types', () => {
|
|
371
|
-
it('should throw and identify custom error', async () => {
|
|
372
|
-
await expect(asyncFunction()).rejects.toThrow(WorkflowAggregateError);
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
it('should validate custom error properties', async () => {
|
|
376
|
-
try {
|
|
377
|
-
await asyncFunction();
|
|
378
|
-
expect.fail('Expected WorkflowAggregateError');
|
|
379
|
-
} catch (error) {
|
|
380
|
-
expect(error).toBeInstanceOf(WorkflowAggregateError);
|
|
381
|
-
if (error instanceof WorkflowAggregateError) {
|
|
382
|
-
expect(error.errors).toHaveLength(3);
|
|
383
|
-
expect(error.failedWorkflowIds).toContain('wf-1');
|
|
384
|
-
expect(error.totalChildren).toBe(5);
|
|
385
|
-
expect(error.failedChildren).toBe(3);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
});
|
|
389
|
-
});
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
### Pattern 2: Testing Wrapped/Merged Errors
|
|
393
|
-
|
|
394
|
-
**Project Pattern from workflow-error-utils.test.ts:**
|
|
395
|
-
|
|
396
|
-
```typescript
|
|
397
|
-
it('should include metadata in original field', () => {
|
|
398
|
-
const error1 = createMockWorkflowError({ workflowId: 'wf-1' });
|
|
399
|
-
const error2 = createMockWorkflowError({ workflowId: 'wf-2' });
|
|
400
|
-
|
|
401
|
-
const result = mergeWorkflowErrors([error1, error2], 'concurrentTask', 'parent-wf', 5);
|
|
402
|
-
|
|
403
|
-
// Access wrapped metadata from original field
|
|
404
|
-
const metadata = result.original as {
|
|
405
|
-
name: string;
|
|
406
|
-
message: string;
|
|
407
|
-
errors: WorkflowError[];
|
|
408
|
-
totalChildren: number;
|
|
409
|
-
failedChildren: number;
|
|
410
|
-
failedWorkflowIds: string[];
|
|
411
|
-
};
|
|
412
|
-
|
|
413
|
-
expect(metadata.name).toBe('WorkflowAggregateError');
|
|
414
|
-
expect(metadata.errors).toEqual([error1, error2]);
|
|
415
|
-
expect(metadata.totalChildren).toBe(5);
|
|
416
|
-
expect(metadata.failedChildren).toBe(2);
|
|
417
|
-
expect(metadata.failedWorkflowIds).toEqual(['wf-1', 'wf-2']);
|
|
418
|
-
});
|
|
419
|
-
```
|
|
420
|
-
|
|
421
|
-
### Pattern 3: Error Property Validation with `expect.objectContaining`
|
|
422
|
-
|
|
423
|
-
```typescript
|
|
424
|
-
it('should validate error structure without type assertion', () => {
|
|
425
|
-
expect(() => throwError()).toThrow(
|
|
426
|
-
expect.objectContaining({
|
|
427
|
-
message: 'Error message',
|
|
428
|
-
code: 'ERROR_CODE',
|
|
429
|
-
workflowId: expect.any(String),
|
|
430
|
-
})
|
|
431
|
-
);
|
|
432
|
-
});
|
|
433
|
-
```
|
|
434
|
-
|
|
435
|
-
### Pattern 4: Testing Error State Preservation
|
|
436
|
-
|
|
437
|
-
```typescript
|
|
438
|
-
it('should use first error state', () => {
|
|
439
|
-
const error1 = createMockWorkflowError({ state: { first: 'state1' } });
|
|
440
|
-
const error2 = createMockWorkflowError({ state: { second: 'state2' } });
|
|
441
|
-
|
|
442
|
-
const result = mergeWorkflowErrors([error1, error2], 'testTask', 'parent-wf', 2);
|
|
443
|
-
|
|
444
|
-
expect(result.state).toEqual({ first: 'state1' });
|
|
445
|
-
});
|
|
446
|
-
|
|
447
|
-
it('should handle undefined state gracefully', () => {
|
|
448
|
-
const error1 = createMockWorkflowError({ state: undefined as any });
|
|
449
|
-
const error2 = createMockWorkflowError({ state: { hasState: 'yes' } });
|
|
450
|
-
|
|
451
|
-
const result = mergeWorkflowErrors([error1, error2], 'testTask', 'parent-wf', 2);
|
|
452
|
-
|
|
453
|
-
expect(result.state).toEqual({});
|
|
454
|
-
});
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
---
|
|
458
|
-
|
|
459
|
-
## Concurrent/Parallel Execution Error Scenarios
|
|
460
|
-
|
|
461
|
-
### Pattern 1: Testing Promise.allSettled Behavior
|
|
462
|
-
|
|
463
|
-
**File Reference:** `/home/dustin/projects/groundswell/src/__tests__/adversarial/concurrent-task-failures.test.ts`
|
|
464
|
-
|
|
465
|
-
Key pattern: Ensure all operations complete despite failures:
|
|
466
|
-
|
|
467
|
-
```typescript
|
|
468
|
-
describe('Single child failure scenarios', () => {
|
|
469
|
-
it('should complete all siblings when one child fails', async () => {
|
|
470
|
-
// ARRANGE: Create parent with 4 children, child[1] will fail
|
|
471
|
-
class ParentWorkflow extends Workflow {
|
|
472
|
-
@Task({ concurrent: true })
|
|
473
|
-
async spawnChildren() {
|
|
474
|
-
return [
|
|
475
|
-
createChildWorkflow(this, 'Child-0', false),
|
|
476
|
-
createChildWorkflow(this, 'Child-1', true), // Will fail
|
|
477
|
-
createChildWorkflow(this, 'Child-2', false),
|
|
478
|
-
createChildWorkflow(this, 'Child-3', false),
|
|
479
|
-
];
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
async run() {
|
|
483
|
-
try {
|
|
484
|
-
await this.spawnChildren();
|
|
485
|
-
} catch (err) {
|
|
486
|
-
// Expected - first error thrown after all complete
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
const parent = new ParentWorkflow('Parent');
|
|
492
|
-
|
|
493
|
-
// ACT: Run parent (children run concurrently)
|
|
494
|
-
await parent.run();
|
|
495
|
-
|
|
496
|
-
// ASSERT: All 4 children attached (Promise.allSettled completed all)
|
|
497
|
-
expect(parent.children.length).toBe(4);
|
|
498
|
-
|
|
499
|
-
// ASSERT: Verify child names match what we created
|
|
500
|
-
const childNames = parent.children.map((c) => (c as any).node.name);
|
|
501
|
-
expect(childNames).toContain('Child-0');
|
|
502
|
-
expect(childNames).toContain('Child-1');
|
|
503
|
-
expect(childNames).toContain('Child-2');
|
|
504
|
-
expect(childNames).toContain('Child-3');
|
|
505
|
-
});
|
|
506
|
-
});
|
|
507
|
-
```
|
|
508
|
-
|
|
509
|
-
### Pattern 2: Testing Multiple Concurrent Failures
|
|
510
|
-
|
|
511
|
-
```typescript
|
|
512
|
-
describe('Multiple concurrent failures', () => {
|
|
513
|
-
it('should collect all errors when multiple children fail concurrently', async () => {
|
|
514
|
-
// ARRANGE: Create parent with 6 children, 3 will fail
|
|
515
|
-
class ParentWorkflow extends Workflow {
|
|
516
|
-
@Task({ concurrent: true })
|
|
517
|
-
async spawnChildren() {
|
|
518
|
-
return [
|
|
519
|
-
createChildWorkflow(this, 'Alpha', false),
|
|
520
|
-
createChildWorkflow(this, 'Beta', true), // Will fail
|
|
521
|
-
createChildWorkflow(this, 'Gamma', false),
|
|
522
|
-
createChildWorkflow(this, 'Delta', true), // Will fail
|
|
523
|
-
createChildWorkflow(this, 'Epsilon', false),
|
|
524
|
-
createChildWorkflow(this, 'Zeta', true), // Will fail
|
|
525
|
-
];
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
async run() {
|
|
529
|
-
try {
|
|
530
|
-
await this.spawnChildren();
|
|
531
|
-
} catch (err) {
|
|
532
|
-
// Expected
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
const parent = new ParentWorkflow('Parent');
|
|
538
|
-
await parent.run();
|
|
539
|
-
|
|
540
|
-
// ASSERT: All 6 children attached (Promise.allSettled completed all)
|
|
541
|
-
expect(parent.children.length).toBe(6);
|
|
542
|
-
});
|
|
543
|
-
});
|
|
544
|
-
```
|
|
545
|
-
|
|
546
|
-
### Pattern 3: Event Emission Verification
|
|
547
|
-
|
|
548
|
-
```typescript
|
|
549
|
-
function setupEventObserver(workflow: Workflow): WorkflowEvent[] {
|
|
550
|
-
const events: WorkflowEvent[] = [];
|
|
551
|
-
workflow.addObserver({
|
|
552
|
-
onLog: () => {},
|
|
553
|
-
onEvent: (e) => events.push(e),
|
|
554
|
-
onStateUpdated: () => {},
|
|
555
|
-
onTreeChanged: () => {},
|
|
556
|
-
});
|
|
557
|
-
return events;
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
it('should emit error events for all failing workflows', async () => {
|
|
561
|
-
class ParentWorkflow extends Workflow {
|
|
562
|
-
@Task({ concurrent: true })
|
|
563
|
-
async spawnChildren() {
|
|
564
|
-
return [
|
|
565
|
-
createChildWorkflow(this, 'Good', false),
|
|
566
|
-
createChildWorkflow(this, 'Bad1', true),
|
|
567
|
-
createChildWorkflow(this, 'Bad2', true),
|
|
568
|
-
];
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
async run() {
|
|
572
|
-
try {
|
|
573
|
-
await this.spawnChildren();
|
|
574
|
-
} catch (err) {
|
|
575
|
-
// Expected
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
const parent = new ParentWorkflow('Parent');
|
|
581
|
-
const events: WorkflowEvent[] = [];
|
|
582
|
-
|
|
583
|
-
// CRITICAL: Add observer to root workflow
|
|
584
|
-
parent.addObserver({
|
|
585
|
-
onLog: () => {},
|
|
586
|
-
onEvent: (e) => events.push(e),
|
|
587
|
-
onStateUpdated: () => {},
|
|
588
|
-
onTreeChanged: () => {},
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
await parent.run();
|
|
592
|
-
|
|
593
|
-
// ASSERT: Error events emitted for both failures
|
|
594
|
-
const errorEvents = events.filter((e) => e.type === 'error');
|
|
595
|
-
expect(errorEvents.length).toBeGreaterThanOrEqual(2);
|
|
596
|
-
|
|
597
|
-
// ASSERT: Each error event has correct structure
|
|
598
|
-
errorEvents.forEach((event) => {
|
|
599
|
-
expect(event.type).toBe('error');
|
|
600
|
-
if (event.type === 'error') {
|
|
601
|
-
expect(event.error).toBeDefined();
|
|
602
|
-
expect(event.error.workflowId).toBeDefined();
|
|
603
|
-
expect(event.error.message).toBeDefined();
|
|
604
|
-
expect(Array.isArray(event.error.logs)).toBe(true);
|
|
605
|
-
}
|
|
606
|
-
});
|
|
607
|
-
});
|
|
608
|
-
```
|
|
609
|
-
|
|
610
|
-
### Pattern 4: Completion Tracking (No Orphaned Promises)
|
|
611
|
-
|
|
612
|
-
```typescript
|
|
613
|
-
it('should ensure no orphaned workflows in mixed scenario', async () => {
|
|
614
|
-
// ARRANGE: Track all completions
|
|
615
|
-
const completedWorkflows = new Set<string>();
|
|
616
|
-
|
|
617
|
-
class ParentWorkflow extends Workflow {
|
|
618
|
-
@Task({ concurrent: true })
|
|
619
|
-
async spawnChildren() {
|
|
620
|
-
const children = [
|
|
621
|
-
createChildWorkflow(this, 'Alpha', false),
|
|
622
|
-
createChildWorkflow(this, 'Beta', true),
|
|
623
|
-
createChildWorkflow(this, 'Gamma', false),
|
|
624
|
-
];
|
|
625
|
-
|
|
626
|
-
// Track completion for all children
|
|
627
|
-
children.forEach((child) => {
|
|
628
|
-
child.run().then(
|
|
629
|
-
() => completedWorkflows.add(child.id),
|
|
630
|
-
() => completedWorkflows.add(child.id)
|
|
631
|
-
);
|
|
632
|
-
});
|
|
633
|
-
|
|
634
|
-
return children;
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
async run() {
|
|
638
|
-
try {
|
|
639
|
-
await this.spawnChildren();
|
|
640
|
-
} catch (err) {
|
|
641
|
-
// Expected
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
const parent = new ParentWorkflow('Parent');
|
|
647
|
-
await parent.run();
|
|
648
|
-
|
|
649
|
-
// ASSERT: All workflows accounted for (no orphans)
|
|
650
|
-
expect(completedWorkflows.size).toBe(3);
|
|
651
|
-
expect(parent.children.length).toBe(3);
|
|
652
|
-
});
|
|
653
|
-
```
|
|
654
|
-
|
|
655
|
-
### Pattern 5: Log Capture from Concurrent Operations
|
|
656
|
-
|
|
657
|
-
```typescript
|
|
658
|
-
it('should capture logs from both successful and failed workflows', async () => {
|
|
659
|
-
class ChildWorkflow extends Workflow {
|
|
660
|
-
private shouldFail: boolean;
|
|
661
|
-
|
|
662
|
-
constructor(name: string, parent: Workflow, shouldFail: boolean) {
|
|
663
|
-
super(name, parent);
|
|
664
|
-
this.shouldFail = shouldFail;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
@Step()
|
|
668
|
-
async executeStep() {
|
|
669
|
-
this.logger.info(`${this.node.name} is running`);
|
|
670
|
-
if (this.shouldFail) {
|
|
671
|
-
this.logger.error(`${this.node.name} is about to fail`);
|
|
672
|
-
throw new Error(`${this.node.name} failed`);
|
|
673
|
-
}
|
|
674
|
-
this.logger.info(`${this.node.name} completed successfully`);
|
|
675
|
-
return `${this.node.name} succeeded`;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
async run() {
|
|
679
|
-
return this.executeStep();
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
class ParentWorkflow extends Workflow {
|
|
684
|
-
@Task({ concurrent: true })
|
|
685
|
-
async spawnChildren() {
|
|
686
|
-
return [
|
|
687
|
-
new ChildWorkflow('SuccessChild', this, false),
|
|
688
|
-
new ChildWorkflow('FailChild', this, true),
|
|
689
|
-
];
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
async run() {
|
|
693
|
-
try {
|
|
694
|
-
await this.spawnChildren();
|
|
695
|
-
} catch (err) {
|
|
696
|
-
// Expected
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
const parent = new ParentWorkflow('Parent');
|
|
702
|
-
const allLogs: string[] = [];
|
|
703
|
-
|
|
704
|
-
parent.addObserver({
|
|
705
|
-
onLog: (entry) => allLogs.push(entry.message),
|
|
706
|
-
onEvent: () => {},
|
|
707
|
-
onStateUpdated: () => {},
|
|
708
|
-
onTreeChanged: () => {},
|
|
709
|
-
});
|
|
710
|
-
|
|
711
|
-
await parent.run();
|
|
712
|
-
|
|
713
|
-
// ASSERT: Logs from both children captured
|
|
714
|
-
expect(allLogs.some((msg) => msg.includes('SuccessChild is running'))).toBe(true);
|
|
715
|
-
expect(allLogs.some((msg) => msg.includes('FailChild is about to fail'))).toBe(true);
|
|
716
|
-
});
|
|
717
|
-
```
|
|
718
|
-
|
|
719
|
-
---
|
|
720
|
-
|
|
721
|
-
## Common Gotchas and Pitfalls
|
|
722
|
-
|
|
723
|
-
### Gotcha 1: Forgetting `await` with `rejects.toThrow()`
|
|
724
|
-
|
|
725
|
-
```typescript
|
|
726
|
-
// BAD - Test will pass even if function doesn't throw
|
|
727
|
-
it('bad example', () => {
|
|
728
|
-
expect(asyncFunction()).rejects.toThrow();
|
|
729
|
-
});
|
|
730
|
-
|
|
731
|
-
// GOOD
|
|
732
|
-
it('good example', async () => {
|
|
733
|
-
await expect(asyncFunction()).rejects.toThrow();
|
|
734
|
-
});
|
|
735
|
-
```
|
|
736
|
-
|
|
737
|
-
### Gotcha 2: Not Handling Expected Errors
|
|
738
|
-
|
|
739
|
-
```typescript
|
|
740
|
-
// BAD - Test will fail due to unhandled error
|
|
741
|
-
it('bad example', async () => {
|
|
742
|
-
await expect(asyncFunction()).rejects.toThrow();
|
|
743
|
-
await expect(anotherAsyncFunction()).rejects.toThrow(); // Never runs if first throws
|
|
744
|
-
});
|
|
745
|
-
|
|
746
|
-
// GOOD - Handle expected errors
|
|
747
|
-
it('good example', async () => {
|
|
748
|
-
try {
|
|
749
|
-
await asyncFunction();
|
|
750
|
-
} catch (err) {
|
|
751
|
-
// Expected
|
|
752
|
-
}
|
|
753
|
-
await expect(anotherAsyncFunction()).rejects.toThrow();
|
|
754
|
-
});
|
|
755
|
-
```
|
|
756
|
-
|
|
757
|
-
### Gotcha 3: Race Conditions in Concurrent Tests
|
|
758
|
-
|
|
759
|
-
```typescript
|
|
760
|
-
// BAD - Non-deterministic results
|
|
761
|
-
it('bad example', async () => {
|
|
762
|
-
const promises = [asyncFn1(), asyncFn2(), asyncFn3()];
|
|
763
|
-
await Promise.all(promises);
|
|
764
|
-
// May fail if promises complete in different order
|
|
765
|
-
});
|
|
766
|
-
|
|
767
|
-
// GOOD - Use Promise.allSettled and track completion
|
|
768
|
-
it('good example', async () => {
|
|
769
|
-
const completed = new Set<string>();
|
|
770
|
-
const promises = [
|
|
771
|
-
asyncFn1().finally(() => completed.add('fn1')),
|
|
772
|
-
asyncFn2().finally(() => completed.add('fn2')),
|
|
773
|
-
asyncFn3().finally(() => completed.add('fn3')),
|
|
774
|
-
];
|
|
775
|
-
await Promise.allSettled(promises);
|
|
776
|
-
expect(completed.size).toBe(3);
|
|
777
|
-
});
|
|
778
|
-
```
|
|
779
|
-
|
|
780
|
-
### Gotcha 4: Type Assertions Without Guards
|
|
781
|
-
|
|
782
|
-
```typescript
|
|
783
|
-
// BAD - Unsafe type assertion
|
|
784
|
-
it('bad example', async () => {
|
|
785
|
-
try {
|
|
786
|
-
await asyncFunction();
|
|
787
|
-
} catch (error) {
|
|
788
|
-
expect((error as CustomError).code).toBe(404); // May crash if not CustomError
|
|
789
|
-
}
|
|
790
|
-
});
|
|
791
|
-
|
|
792
|
-
// GOOD - Use type guards
|
|
793
|
-
it('good example', async () => {
|
|
794
|
-
try {
|
|
795
|
-
await asyncFunction();
|
|
796
|
-
} catch (error) {
|
|
797
|
-
expect(error).toBeInstanceOf(CustomError);
|
|
798
|
-
if (error instanceof CustomError) {
|
|
799
|
-
expect(error.code).toBe(404);
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
});
|
|
803
|
-
```
|
|
804
|
-
|
|
805
|
-
### Gotcha 5: Not Testing All Concurrent Scenarios
|
|
806
|
-
|
|
807
|
-
```typescript
|
|
808
|
-
// BAD - Only tests failure case
|
|
809
|
-
it('bad example', async () => {
|
|
810
|
-
await expect(failingTask()).rejects.toThrow();
|
|
811
|
-
});
|
|
812
|
-
|
|
813
|
-
// GOOD - Test all scenarios: all fail, some fail, none fail
|
|
814
|
-
describe('concurrent task scenarios', () => {
|
|
815
|
-
it('should handle all failing', async () => { /* ... */ });
|
|
816
|
-
it('should handle some failing', async () => { /* ... */ });
|
|
817
|
-
it('should handle none failing', async () => { /* ... */ });
|
|
818
|
-
});
|
|
819
|
-
```
|
|
820
|
-
|
|
821
|
-
### Gotcha 6: Hanging Promises in Concurrent Tests
|
|
822
|
-
|
|
823
|
-
```typescript
|
|
824
|
-
// BAD - Test may hang indefinitely
|
|
825
|
-
it('bad example', async () => {
|
|
826
|
-
const promises = [asyncFn1(), asyncFn2()];
|
|
827
|
-
// If one hangs, test never completes
|
|
828
|
-
await Promise.all(promises);
|
|
829
|
-
});
|
|
830
|
-
|
|
831
|
-
// GOOD - Use timeout
|
|
832
|
-
it('good example', async () => {
|
|
833
|
-
const timeoutPromise = new Promise((_, reject) =>
|
|
834
|
-
setTimeout(() => reject(new Error('Timeout')), 5000)
|
|
835
|
-
);
|
|
836
|
-
|
|
837
|
-
const runPromise = Promise.all([asyncFn1(), asyncFn2()]);
|
|
838
|
-
await Promise.race([runPromise, timeoutPromise]);
|
|
839
|
-
});
|
|
840
|
-
```
|
|
841
|
-
|
|
842
|
-
### Gotcha 7: Not Verifying Error Properties
|
|
843
|
-
|
|
844
|
-
```typescript
|
|
845
|
-
// BAD - Only checks that error was thrown
|
|
846
|
-
it('bad example', async () => {
|
|
847
|
-
await expect(asyncFunction()).rejects.toThrow();
|
|
848
|
-
});
|
|
849
|
-
|
|
850
|
-
// GOOD - Verify error structure
|
|
851
|
-
it('good example', async () => {
|
|
852
|
-
await expect(asyncFunction()).rejects.toThrow(expect.objectContaining({
|
|
853
|
-
message: 'specific message',
|
|
854
|
-
code: 'SPECIFIC_ERROR',
|
|
855
|
-
workflowId: expect.any(String),
|
|
856
|
-
}));
|
|
857
|
-
});
|
|
858
|
-
```
|
|
859
|
-
|
|
860
|
-
### Gotcha 8: Missing Observer Setup for Event Testing
|
|
861
|
-
|
|
862
|
-
```typescript
|
|
863
|
-
// BAD - Events won't be captured
|
|
864
|
-
it('bad example', async () => {
|
|
865
|
-
const parent = new ParentWorkflow('Parent');
|
|
866
|
-
await parent.run();
|
|
867
|
-
expect(events.length).toBe(0); // Events array doesn't exist!
|
|
868
|
-
});
|
|
869
|
-
|
|
870
|
-
// GOOD - Setup observer before execution
|
|
871
|
-
it('good example', async () => {
|
|
872
|
-
const parent = new ParentWorkflow('Parent');
|
|
873
|
-
const events: WorkflowEvent[] = [];
|
|
874
|
-
|
|
875
|
-
// CRITICAL: Add observer BEFORE running
|
|
876
|
-
parent.addObserver({
|
|
877
|
-
onLog: () => {},
|
|
878
|
-
onEvent: (e) => events.push(e),
|
|
879
|
-
onStateUpdated: () => {},
|
|
880
|
-
onTreeChanged: () => {},
|
|
881
|
-
});
|
|
882
|
-
|
|
883
|
-
await parent.run();
|
|
884
|
-
expect(events.length).toBeGreaterThan(0);
|
|
885
|
-
});
|
|
886
|
-
```
|
|
887
|
-
|
|
888
|
-
---
|
|
889
|
-
|
|
890
|
-
## Project-Specific Testing Patterns
|
|
891
|
-
|
|
892
|
-
### Pattern 1: Helper Functions for Test Data Creation
|
|
893
|
-
|
|
894
|
-
**From workflow-error-utils.test.ts:**
|
|
895
|
-
|
|
896
|
-
```typescript
|
|
897
|
-
function createMockWorkflowError(overrides?: Partial<WorkflowError>): WorkflowError {
|
|
898
|
-
return {
|
|
899
|
-
message: 'Test error',
|
|
900
|
-
original: new Error('Original error'),
|
|
901
|
-
workflowId: 'wf-test-123',
|
|
902
|
-
stack: 'Error: Test error\n at test.ts:10:15',
|
|
903
|
-
state: { key: 'value' },
|
|
904
|
-
logs: [
|
|
905
|
-
{
|
|
906
|
-
id: 'log-1',
|
|
907
|
-
workflowId: 'wf-test-123',
|
|
908
|
-
timestamp: Date.now(),
|
|
909
|
-
level: 'error',
|
|
910
|
-
message: 'Test log message',
|
|
911
|
-
},
|
|
912
|
-
],
|
|
913
|
-
...overrides,
|
|
914
|
-
};
|
|
915
|
-
}
|
|
916
|
-
```
|
|
917
|
-
|
|
918
|
-
### Pattern 2: Deterministic Child Workflow Creation
|
|
919
|
-
|
|
920
|
-
**From concurrent-task-failures.test.ts:**
|
|
921
|
-
|
|
922
|
-
```typescript
|
|
923
|
-
function createChildWorkflow(
|
|
924
|
-
parent: Workflow,
|
|
925
|
-
name: string,
|
|
926
|
-
shouldFail: boolean = false
|
|
927
|
-
): Workflow {
|
|
928
|
-
return new (class extends Workflow {
|
|
929
|
-
constructor(n: string, p: Workflow) {
|
|
930
|
-
super(n, p);
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
@Step()
|
|
934
|
-
async executeStep() {
|
|
935
|
-
if (shouldFail) {
|
|
936
|
-
throw new Error(`${name} failed`);
|
|
937
|
-
}
|
|
938
|
-
return `${name} succeeded`;
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
async run() {
|
|
942
|
-
return this.executeStep();
|
|
943
|
-
}
|
|
944
|
-
})(name, parent);
|
|
945
|
-
}
|
|
946
|
-
```
|
|
947
|
-
|
|
948
|
-
### Pattern 3: Event Observer Setup Pattern
|
|
949
|
-
|
|
950
|
-
```typescript
|
|
951
|
-
function setupEventObserver(workflow: Workflow): WorkflowEvent[] {
|
|
952
|
-
const events: WorkflowEvent[] = [];
|
|
953
|
-
workflow.addObserver({
|
|
954
|
-
onLog: () => {},
|
|
955
|
-
onEvent: (e) => events.push(e),
|
|
956
|
-
onStateUpdated: () => {},
|
|
957
|
-
onTreeChanged: () => {},
|
|
958
|
-
});
|
|
959
|
-
return events;
|
|
960
|
-
}
|
|
961
|
-
```
|
|
962
|
-
|
|
963
|
-
### Pattern 4: Comprehensive Test Organization
|
|
964
|
-
|
|
965
|
-
**From concurrent-task-failures.test.ts:**
|
|
966
|
-
|
|
967
|
-
```typescript
|
|
968
|
-
describe('@Task decorator concurrent failure scenarios', () => {
|
|
969
|
-
describe('Single child failure scenarios', () => {
|
|
970
|
-
it('should complete all siblings when one child fails', async () => {
|
|
971
|
-
// ARRANGE: Create parent with 4 children, child[1] will fail
|
|
972
|
-
// ACT: Run parent (children run concurrently)
|
|
973
|
-
// ASSERT: All 4 children attached (Promise.allSettled completed all)
|
|
974
|
-
});
|
|
975
|
-
});
|
|
976
|
-
|
|
977
|
-
describe('Multiple concurrent failures', () => {
|
|
978
|
-
it('should collect all errors when multiple children fail concurrently', async () => {
|
|
979
|
-
// ...
|
|
980
|
-
});
|
|
981
|
-
});
|
|
982
|
-
|
|
983
|
-
describe('Mixed success/failure scenarios', () => {
|
|
984
|
-
it('should complete successful workflows despite failures', async () => {
|
|
985
|
-
// ...
|
|
986
|
-
});
|
|
987
|
-
});
|
|
988
|
-
|
|
989
|
-
describe('All children failing', () => {
|
|
990
|
-
it('should handle edge case of all children failing', async () => {
|
|
991
|
-
// ...
|
|
992
|
-
});
|
|
993
|
-
});
|
|
994
|
-
|
|
995
|
-
describe('No orphaned workflows', () => {
|
|
996
|
-
it('should verify all workflows complete with no hanging promises', async () => {
|
|
997
|
-
// ...
|
|
998
|
-
});
|
|
999
|
-
});
|
|
1000
|
-
|
|
1001
|
-
describe('Event emission verification', () => {
|
|
1002
|
-
it('should emit error events for all failing workflows', async () => {
|
|
1003
|
-
// ...
|
|
1004
|
-
});
|
|
1005
|
-
});
|
|
1006
|
-
});
|
|
1007
|
-
```
|
|
1008
|
-
|
|
1009
|
-
---
|
|
1010
|
-
|
|
1011
|
-
## Summary of Key Testing Patterns
|
|
1012
|
-
|
|
1013
|
-
### For Error Aggregation:
|
|
1014
|
-
1. Test single error case (edge case)
|
|
1015
|
-
2. Test multiple error aggregation
|
|
1016
|
-
3. Test deduplication of IDs
|
|
1017
|
-
4. Test array flattening (logs, etc.)
|
|
1018
|
-
5. Test metadata preservation in wrapped errors
|
|
1019
|
-
6. Test state/stack selection strategies (first error wins)
|
|
1020
|
-
|
|
1021
|
-
### For Async Errors:
|
|
1022
|
-
1. Use `await expect().rejects.toThrow()` for basic cases
|
|
1023
|
-
2. Use try-catch for detailed error inspection
|
|
1024
|
-
3. Use `expect.fail()` for unexpected success
|
|
1025
|
-
4. Test error messages with string or regex
|
|
1026
|
-
5. Test error types with constructors
|
|
1027
|
-
6. Handle expected errors gracefully
|
|
1028
|
-
|
|
1029
|
-
### For Custom Errors:
|
|
1030
|
-
1. Test with `toBeInstanceOf()` and custom error class
|
|
1031
|
-
2. Use type guards before accessing custom properties
|
|
1032
|
-
3. Test wrapped error metadata through `original` field
|
|
1033
|
-
4. Use `expect.objectContaining()` for partial matching
|
|
1034
|
-
5. Test state preservation and handling of undefined values
|
|
1035
|
-
|
|
1036
|
-
### For Concurrent Execution:
|
|
1037
|
-
1. Test all scenarios: all fail, some fail, none fail
|
|
1038
|
-
2. Use `Promise.allSettled()` patterns for completion verification
|
|
1039
|
-
3. Track completion with Sets to detect orphaned operations
|
|
1040
|
-
4. Setup event observers before execution
|
|
1041
|
-
5. Use timeouts to detect hanging promises
|
|
1042
|
-
6. Verify logs from both successful and failed operations
|
|
1043
|
-
|
|
1044
|
-
### Common Pitfalls to Avoid:
|
|
1045
|
-
1. Forgetting `await` with `rejects.toThrow()`
|
|
1046
|
-
2. Not handling expected errors in test flow
|
|
1047
|
-
3. Race conditions from improper promise handling
|
|
1048
|
-
4. Unsafe type assertions without guards
|
|
1049
|
-
5. Not testing all concurrent scenarios
|
|
1050
|
-
6. Hanging promises from missing timeouts
|
|
1051
|
-
7. Not verifying error properties thoroughly
|
|
1052
|
-
8. Missing observer setup for event testing
|
|
1053
|
-
|
|
1054
|
-
---
|
|
1055
|
-
|
|
1056
|
-
## Additional Resources
|
|
1057
|
-
|
|
1058
|
-
### Project Test Files Referenced:
|
|
1059
|
-
- `/home/dustin/projects/groundswell/src/__tests__/unit/utils/workflow-error-utils.test.ts`
|
|
1060
|
-
- `/home/dustin/projects/groundswell/src/__tests__/adversarial/concurrent-task-failures.test.ts`
|
|
1061
|
-
|
|
1062
|
-
### Related Types:
|
|
1063
|
-
- `/home/dustin/projects/groundswell/src/types/error.ts` - WorkflowError interface
|
|
1064
|
-
|
|
1065
|
-
### Configuration:
|
|
1066
|
-
- `/home/dustin/projects/groundswell/vitest.config.ts` - Test configuration
|
|
1067
|
-
- `/home/dustin/projects/groundswell/package.json` - Dependencies and scripts
|
|
1068
|
-
|
|
1069
|
-
---
|
|
1070
|
-
|
|
1071
|
-
## Quick Reference: Vitest Error Testing Assertions
|
|
1072
|
-
|
|
1073
|
-
```typescript
|
|
1074
|
-
// Synchronous errors
|
|
1075
|
-
expect(() => syncFunction()).toThrow()
|
|
1076
|
-
expect(() => syncFunction()).toThrow(Error)
|
|
1077
|
-
expect(() => syncFunction()).toThrow('message')
|
|
1078
|
-
expect(() => syncFunction()).toThrow(/regex/)
|
|
1079
|
-
expect(() => syncFunction()).toThrow(CustomError)
|
|
1080
|
-
|
|
1081
|
-
// Async errors
|
|
1082
|
-
await expect(asyncFunction()).rejects.toThrow()
|
|
1083
|
-
await expect(asyncFunction()).rejects.toThrow(Error)
|
|
1084
|
-
await expect(asyncFunction()).rejects.toThrow('message')
|
|
1085
|
-
await expect(asyncFunction()).rejects.toThrow(/regex/)
|
|
1086
|
-
await expect(asyncFunction()).rejects.toThrow(CustomError)
|
|
1087
|
-
|
|
1088
|
-
// Error property matching
|
|
1089
|
-
expect(() => throwError()).toThrow(
|
|
1090
|
-
expect.objectContaining({
|
|
1091
|
-
message: 'specific',
|
|
1092
|
-
code: 'CODE',
|
|
1093
|
-
})
|
|
1094
|
-
)
|
|
1095
|
-
|
|
1096
|
-
// Instance checking
|
|
1097
|
-
expect(error).toBeInstanceOf(Error)
|
|
1098
|
-
expect(error).toBeInstanceOf(CustomError)
|
|
1099
|
-
```
|
|
1100
|
-
|
|
1101
|
-
---
|
|
1102
|
-
|
|
1103
|
-
*End of Research Report*
|