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,1014 +0,0 @@
|
|
|
1
|
-
# Test Pattern Examples for Bidirectional Tree Consistency
|
|
2
|
-
|
|
3
|
-
**Companion to:** bidirectional-tree-consistency-testing.md
|
|
4
|
-
**Purpose:** Provide copy-paste ready test patterns for immediate implementation
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Quick Reference: Helper Functions
|
|
9
|
-
|
|
10
|
-
```typescript
|
|
11
|
-
// File: src/__tests__/helpers/tree-verification.ts
|
|
12
|
-
|
|
13
|
-
import type { Workflow } from '../../index.js';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Collect all nodes in tree via BFS
|
|
17
|
-
* Throws if circular reference detected
|
|
18
|
-
*/
|
|
19
|
-
export function collectAllNodes(root: Workflow): Workflow[] {
|
|
20
|
-
const nodes: Workflow[] = [];
|
|
21
|
-
const queue: Workflow[] = [root];
|
|
22
|
-
const visited = new Set<Workflow>();
|
|
23
|
-
|
|
24
|
-
while (queue.length > 0) {
|
|
25
|
-
const node = queue.shift()!;
|
|
26
|
-
|
|
27
|
-
if (visited.has(node)) {
|
|
28
|
-
throw new Error(`Circular reference detected at ${node.node.name}`);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
visited.add(node);
|
|
32
|
-
nodes.push(node);
|
|
33
|
-
queue.push(...node.children);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return nodes;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Validate tree-wide bidirectional consistency
|
|
41
|
-
* Returns array of inconsistency descriptions (empty if valid)
|
|
42
|
-
*/
|
|
43
|
-
export function validateTreeConsistency(root: Workflow): string[] {
|
|
44
|
-
const errors: string[] = [];
|
|
45
|
-
const allNodes = collectAllNodes(root);
|
|
46
|
-
|
|
47
|
-
allNodes.forEach(node => {
|
|
48
|
-
// Check parent→child link in workflow tree
|
|
49
|
-
if (node.parent) {
|
|
50
|
-
if (!node.parent.children.includes(node)) {
|
|
51
|
-
errors.push(
|
|
52
|
-
`[WORKFLOW TREE] Orphaned child: "${node.node.name}" not in parent "${node.parent.node.name}"'s children list`
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
} else {
|
|
56
|
-
// Root node - should not be in anyone's children
|
|
57
|
-
const parentClaimants = allNodes.filter(n => n.children.includes(node));
|
|
58
|
-
if (parentClaimants.length > 0) {
|
|
59
|
-
errors.push(
|
|
60
|
-
`[WORKFLOW TREE] Root node "${node.node.name}" claimed as child by [${parentClaimants.map(n => n.node.name).join(', ')}]`
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Check child→parent links
|
|
66
|
-
node.children.forEach(child => {
|
|
67
|
-
if (child.parent !== node) {
|
|
68
|
-
errors.push(
|
|
69
|
-
`[WORKFLOW TREE] Mismatched parent: "${child.node.name}".parent is "${child.parent?.node.name ?? 'null'}", expected "${node.node.name}"`
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Check node tree mirrors workflow tree - parent relationship
|
|
74
|
-
if (child.node.parent !== node.node) {
|
|
75
|
-
errors.push(
|
|
76
|
-
`[NODE TREE] Mismatched parent: "${child.node.name}".node.parent is "${child.node.parent?.name ?? 'null'}", expected "${node.node.name}"`
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Check node tree mirrors workflow tree - children relationship
|
|
81
|
-
if (!node.node.children.includes(child.node)) {
|
|
82
|
-
errors.push(
|
|
83
|
-
`[NODE TREE] Orphaned child: "${child.node.name}".node not in parent "${node.node.name}"'s node.children array`
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
return errors;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Verify bidirectional link between parent and child in BOTH trees
|
|
94
|
-
* Throws if inconsistency found
|
|
95
|
-
*/
|
|
96
|
-
export function verifyBidirectionalLink(parent: Workflow, child: Workflow): void {
|
|
97
|
-
// Workflow tree checks
|
|
98
|
-
if (child.parent !== parent) {
|
|
99
|
-
throw new Error(
|
|
100
|
-
`[WORKFLOW TREE] Bidirectional link broken: "${child.node.name}".parent is "${child.parent?.node.name ?? 'null'}", expected "${parent.node.name}"`
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (!parent.children.includes(child)) {
|
|
105
|
-
throw new Error(
|
|
106
|
-
`[WORKFLOW TREE] Bidirectional link broken: "${parent.node.name}".children does not contain "${child.node.name}"`
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Node tree checks (must mirror workflow tree)
|
|
111
|
-
if (child.node.parent !== parent.node) {
|
|
112
|
-
throw new Error(
|
|
113
|
-
`[NODE TREE] Bidirectional link broken: "${child.node.name}".node.parent is "${child.node.parent?.name ?? 'null'}", expected "${parent.node.name}"`
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (!parent.node.children.includes(child.node)) {
|
|
118
|
-
throw new Error(
|
|
119
|
-
`[NODE TREE] Bidirectional link broken: "${parent.node.name}".node.children does not contain "${child.node.name}"`
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Verify complete orphaning after detach
|
|
126
|
-
*/
|
|
127
|
-
export function verifyOrphaned(child: Workflow): void {
|
|
128
|
-
if (child.parent !== null) {
|
|
129
|
-
throw new Error(
|
|
130
|
-
`Child "${child.node.name}" not orphaned: parent is "${child.parent.node.name}"`
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (child.node.parent !== null) {
|
|
135
|
-
throw new Error(
|
|
136
|
-
`Child "${child.node.name}" not orphaned in node tree: parent is "${child.node.parent.name}"`
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Verify no circular references exist
|
|
143
|
-
*/
|
|
144
|
-
export function verifyNoCycles(root: Workflow): void {
|
|
145
|
-
const visited = new Set<Workflow>();
|
|
146
|
-
const allNodes = collectAllNodes(root);
|
|
147
|
-
|
|
148
|
-
allNodes.forEach(node => {
|
|
149
|
-
if (visited.has(node)) {
|
|
150
|
-
throw new Error(`Circular reference detected: node "${node.node.name}" visited twice`);
|
|
151
|
-
}
|
|
152
|
-
visited.add(node);
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Verify tree mirror invariant (1:1 correspondence)
|
|
158
|
-
*/
|
|
159
|
-
export function verifyTreeMirror(workflowRoot: Workflow): void {
|
|
160
|
-
const allNodes = collectAllNodes(workflowRoot);
|
|
161
|
-
|
|
162
|
-
allNodes.forEach(wfNode => {
|
|
163
|
-
const node = wfNode.node;
|
|
164
|
-
|
|
165
|
-
// Verify parent relationship mirrors
|
|
166
|
-
if (wfNode.parent) {
|
|
167
|
-
if (node.parent !== wfNode.parent.node) {
|
|
168
|
-
throw new Error(
|
|
169
|
-
`[MIRROR] Parent mismatch: "${wfNode.node.name}".parent is "${node.parent?.name}", expected "${wfNode.parent.node.name}"`
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
} else {
|
|
173
|
-
if (node.parent !== null) {
|
|
174
|
-
throw new Error(
|
|
175
|
-
`[MIRROR] Parent mismatch: "${wfNode.node.name}".parent is "${node.parent.name}", expected null`
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Verify children relationship mirrors
|
|
181
|
-
if (node.children.length !== wfNode.children.length) {
|
|
182
|
-
throw new Error(
|
|
183
|
-
`[MIRROR] Children count mismatch: "${wfNode.node.name}" has ${wfNode.children.length} workflow children but ${node.children.length} node children`
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
wfNode.children.forEach((childWf, index) => {
|
|
188
|
-
if (node.children[index] !== childWf.node) {
|
|
189
|
-
throw new Error(
|
|
190
|
-
`[MIRROR] Child mismatch at index ${index}: expected "${childWf.node.name}", got "${node.children[index].name}"`
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Get depth of node in tree
|
|
199
|
-
*/
|
|
200
|
-
export function getDepth(node: Workflow): number {
|
|
201
|
-
let depth = 0;
|
|
202
|
-
let current: Workflow | null = node;
|
|
203
|
-
|
|
204
|
-
while (current !== null) {
|
|
205
|
-
depth++;
|
|
206
|
-
current = current.parent;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
return depth - 1; // Subtract 1 for the node itself
|
|
210
|
-
}
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
## Pattern 1: Basic Bidirectional Consistency Test
|
|
216
|
-
|
|
217
|
-
```typescript
|
|
218
|
-
// File: src/__tests__/integration/bidirectional-consistency.test.ts
|
|
219
|
-
|
|
220
|
-
import { describe, it, expect } from 'vitest';
|
|
221
|
-
import { Workflow } from '../../index.js';
|
|
222
|
-
import {
|
|
223
|
-
verifyBidirectionalLink,
|
|
224
|
-
verifyTreeMirror,
|
|
225
|
-
validateTreeConsistency,
|
|
226
|
-
} from '../helpers/tree-verification';
|
|
227
|
-
|
|
228
|
-
class SimpleWorkflow extends Workflow {
|
|
229
|
-
async run(): Promise<string> {
|
|
230
|
-
this.setStatus('running');
|
|
231
|
-
this.setStatus('completed');
|
|
232
|
-
return 'done';
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
describe('Bidirectional Consistency: Basic Operations', () => {
|
|
237
|
-
describe('attachChild() consistency', () => {
|
|
238
|
-
it('should maintain bidirectional links in both trees', () => {
|
|
239
|
-
const parent = new SimpleWorkflow('Parent');
|
|
240
|
-
const child = new SimpleWorkflow('Child'); // No parent
|
|
241
|
-
|
|
242
|
-
parent.attachChild(child);
|
|
243
|
-
|
|
244
|
-
// Verify bidirectional links
|
|
245
|
-
verifyBidirectionalLink(parent, child);
|
|
246
|
-
|
|
247
|
-
// Verify tree mirror invariant
|
|
248
|
-
verifyTreeMirror(parent);
|
|
249
|
-
|
|
250
|
-
// Verify no inconsistencies detected
|
|
251
|
-
const errors = validateTreeConsistency(parent);
|
|
252
|
-
expect(errors).toEqual([]);
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
it('should maintain consistency when attaching multiple children', () => {
|
|
256
|
-
const parent = new SimpleWorkflow('Parent');
|
|
257
|
-
const child1 = new SimpleWorkflow('Child1');
|
|
258
|
-
const child2 = new SimpleWorkflow('Child2');
|
|
259
|
-
const child3 = new SimpleWorkflow('Child3');
|
|
260
|
-
|
|
261
|
-
parent.attachChild(child1);
|
|
262
|
-
parent.attachChild(child2);
|
|
263
|
-
parent.attachChild(child3);
|
|
264
|
-
|
|
265
|
-
// Verify each child
|
|
266
|
-
verifyBidirectionalLink(parent, child1);
|
|
267
|
-
verifyBidirectionalLink(parent, child2);
|
|
268
|
-
verifyBidirectionalLink(parent, child3);
|
|
269
|
-
|
|
270
|
-
// Verify entire tree
|
|
271
|
-
verifyTreeMirror(parent);
|
|
272
|
-
|
|
273
|
-
const errors = validateTreeConsistency(parent);
|
|
274
|
-
expect(errors).toEqual([]);
|
|
275
|
-
});
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
describe('detachChild() consistency', () => {
|
|
279
|
-
it('should remove bidirectional links from both trees', () => {
|
|
280
|
-
const parent = new SimpleWorkflow('Parent');
|
|
281
|
-
const child = new SimpleWorkflow('Child', parent);
|
|
282
|
-
|
|
283
|
-
parent.detachChild(child);
|
|
284
|
-
|
|
285
|
-
// Verify orphaning
|
|
286
|
-
verifyOrphaned(child);
|
|
287
|
-
|
|
288
|
-
// Verify parent no longer references child
|
|
289
|
-
expect(parent.children).not.toContain(child);
|
|
290
|
-
expect(parent.node.children).not.toContain(child.node);
|
|
291
|
-
|
|
292
|
-
// Verify tree mirror
|
|
293
|
-
verifyTreeMirror(parent);
|
|
294
|
-
|
|
295
|
-
const errors = validateTreeConsistency(parent);
|
|
296
|
-
expect(errors).toEqual([]);
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
it('should maintain consistency when detaching middle child', () => {
|
|
300
|
-
const parent = new SimpleWorkflow('Parent');
|
|
301
|
-
const child1 = new SimpleWorkflow('Child1', parent);
|
|
302
|
-
const child2 = new SimpleWorkflow('Child2', parent);
|
|
303
|
-
const child3 = new SimpleWorkflow('Child3', parent);
|
|
304
|
-
|
|
305
|
-
// Detach middle child
|
|
306
|
-
parent.detachChild(child2);
|
|
307
|
-
|
|
308
|
-
// Verify child2 is orphaned
|
|
309
|
-
verifyOrphaned(child2);
|
|
310
|
-
|
|
311
|
-
// Verify other children still linked
|
|
312
|
-
verifyBidirectionalLink(parent, child1);
|
|
313
|
-
verifyBidirectionalLink(parent, child3);
|
|
314
|
-
|
|
315
|
-
// Verify parent has correct children
|
|
316
|
-
expect(parent.children).toEqual([child1, child3]);
|
|
317
|
-
expect(parent.node.children).toEqual([child1.node, child3.node]);
|
|
318
|
-
|
|
319
|
-
// Verify tree mirror
|
|
320
|
-
verifyTreeMirror(parent);
|
|
321
|
-
|
|
322
|
-
const errors = validateTreeConsistency(parent);
|
|
323
|
-
expect(errors).toEqual([]);
|
|
324
|
-
});
|
|
325
|
-
});
|
|
326
|
-
});
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
---
|
|
330
|
-
|
|
331
|
-
## Pattern 2: Reparenting Consistency Test
|
|
332
|
-
|
|
333
|
-
```typescript
|
|
334
|
-
describe('Bidirectional Consistency: Reparenting', () => {
|
|
335
|
-
it('should maintain consistency during single reparenting', () => {
|
|
336
|
-
const parent1 = new SimpleWorkflow('Parent1');
|
|
337
|
-
const parent2 = new SimpleWorkflow('Parent2');
|
|
338
|
-
const child = new SimpleWorkflow('Child', parent1);
|
|
339
|
-
|
|
340
|
-
// Verify initial state
|
|
341
|
-
verifyBidirectionalLink(parent1, child);
|
|
342
|
-
expect(parent2.children).toEqual([]);
|
|
343
|
-
|
|
344
|
-
// Execute reparenting
|
|
345
|
-
parent1.detachChild(child);
|
|
346
|
-
parent2.attachChild(child);
|
|
347
|
-
|
|
348
|
-
// Verify new state
|
|
349
|
-
verifyBidirectionalLink(parent2, child);
|
|
350
|
-
|
|
351
|
-
// Verify old parent no longer has child
|
|
352
|
-
expect(parent1.children).not.toContain(child);
|
|
353
|
-
expect(parent1.node.children).not.toContain(child.node);
|
|
354
|
-
|
|
355
|
-
// Verify new parent has child
|
|
356
|
-
expect(parent2.children).toContain(child);
|
|
357
|
-
expect(parent2.node.children).toContain(child.node);
|
|
358
|
-
|
|
359
|
-
// Verify tree mirrors
|
|
360
|
-
verifyTreeMirror(parent1);
|
|
361
|
-
verifyTreeMirror(parent2);
|
|
362
|
-
|
|
363
|
-
// Verify no inconsistencies
|
|
364
|
-
const errors1 = validateTreeConsistency(parent1);
|
|
365
|
-
const errors2 = validateTreeConsistency(parent2);
|
|
366
|
-
|
|
367
|
-
expect(errors1).toEqual([]);
|
|
368
|
-
expect(errors2).toEqual([]);
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
it('should maintain consistency during multiple reparenting cycles', () => {
|
|
372
|
-
const parentA = new SimpleWorkflow('ParentA');
|
|
373
|
-
const parentB = new SimpleWorkflow('ParentB');
|
|
374
|
-
const parentC = new SimpleWorkflow('ParentC');
|
|
375
|
-
const child = new SimpleWorkflow('Child', parentA);
|
|
376
|
-
|
|
377
|
-
// Cycle 1: A -> B
|
|
378
|
-
parentA.detachChild(child);
|
|
379
|
-
parentB.attachChild(child);
|
|
380
|
-
|
|
381
|
-
verifyBidirectionalLink(parentB, child);
|
|
382
|
-
verifyTreeMirror(parentB);
|
|
383
|
-
expect(validateTreeConsistency(parentB)).toEqual([]);
|
|
384
|
-
|
|
385
|
-
// Cycle 2: B -> C
|
|
386
|
-
parentB.detachChild(child);
|
|
387
|
-
parentC.attachChild(child);
|
|
388
|
-
|
|
389
|
-
verifyBidirectionalLink(parentC, child);
|
|
390
|
-
verifyTreeMirror(parentC);
|
|
391
|
-
expect(validateTreeConsistency(parentC)).toEqual([]);
|
|
392
|
-
|
|
393
|
-
// Cycle 3: C -> A (back to original)
|
|
394
|
-
parentC.detachChild(child);
|
|
395
|
-
parentA.attachChild(child);
|
|
396
|
-
|
|
397
|
-
verifyBidirectionalLink(parentA, child);
|
|
398
|
-
verifyTreeMirror(parentA);
|
|
399
|
-
expect(validateTreeConsistency(parentA)).toEqual([]);
|
|
400
|
-
});
|
|
401
|
-
|
|
402
|
-
it('should maintain consistency with deep hierarchy reparenting', () => {
|
|
403
|
-
const root1 = new SimpleWorkflow('Root1');
|
|
404
|
-
const mid1 = new SimpleWorkflow('Mid1', root1);
|
|
405
|
-
const leaf = new SimpleWorkflow('Leaf', mid1);
|
|
406
|
-
|
|
407
|
-
const root2 = new SimpleWorkflow('Root2');
|
|
408
|
-
const mid2 = new SimpleWorkflow('Mid2', root2);
|
|
409
|
-
|
|
410
|
-
// Verify initial deep hierarchy
|
|
411
|
-
verifyBidirectionalLink(root1, mid1);
|
|
412
|
-
verifyBidirectionalLink(mid1, leaf);
|
|
413
|
-
verifyTreeMirror(root1);
|
|
414
|
-
|
|
415
|
-
// Reparent entire subtree (mid1 + leaf)
|
|
416
|
-
root1.detachChild(mid1);
|
|
417
|
-
root2.attachChild(mid1);
|
|
418
|
-
|
|
419
|
-
// Verify new hierarchy
|
|
420
|
-
verifyBidirectionalLink(root2, mid1);
|
|
421
|
-
verifyBidirectionalLink(mid1, leaf);
|
|
422
|
-
verifyTreeMirror(root2);
|
|
423
|
-
|
|
424
|
-
// Verify old root no longer has mid1
|
|
425
|
-
expect(root1.children).toEqual([]);
|
|
426
|
-
expect(root1.node.children).toEqual([]);
|
|
427
|
-
|
|
428
|
-
// Verify new root has mid1
|
|
429
|
-
expect(root2.children).toEqual([mid1]);
|
|
430
|
-
expect(root2.node.children).toEqual([mid1.node]);
|
|
431
|
-
|
|
432
|
-
// Verify leaf still under mid1
|
|
433
|
-
expect(mid1.children).toEqual([leaf]);
|
|
434
|
-
expect(mid1.node.children).toEqual([leaf.node]);
|
|
435
|
-
|
|
436
|
-
// Verify no inconsistencies
|
|
437
|
-
expect(validateTreeConsistency(root2)).toEqual([]);
|
|
438
|
-
});
|
|
439
|
-
});
|
|
440
|
-
```
|
|
441
|
-
|
|
442
|
-
---
|
|
443
|
-
|
|
444
|
-
## Pattern 3: Invariant Testing
|
|
445
|
-
|
|
446
|
-
```typescript
|
|
447
|
-
describe('Bidirectional Consistency: Invariants', () => {
|
|
448
|
-
describe('Acyclicity invariant', () => {
|
|
449
|
-
it('should prevent circular references', () => {
|
|
450
|
-
const root = new SimpleWorkflow('Root');
|
|
451
|
-
const child = new SimpleWorkflow('Child', root);
|
|
452
|
-
|
|
453
|
-
// Try to create cycle
|
|
454
|
-
expect(() => {
|
|
455
|
-
child.attachChild(root as any);
|
|
456
|
-
}).toThrow(/circular|cycle/i);
|
|
457
|
-
|
|
458
|
-
// Verify no corruption
|
|
459
|
-
verifyNoCycles(root);
|
|
460
|
-
expect(root.parent).toBeNull();
|
|
461
|
-
expect(child.parent).toBe(root);
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
it('should detect complex circular references', () => {
|
|
465
|
-
const root = new SimpleWorkflow('Root');
|
|
466
|
-
const child1 = new SimpleWorkflow('Child1', root);
|
|
467
|
-
const child2 = new SimpleWorkflow('Child2', child1);
|
|
468
|
-
const child3 = new SimpleWorkflow('Child3', child2);
|
|
469
|
-
|
|
470
|
-
// Try to create cycle: child3 -> root
|
|
471
|
-
expect(() => {
|
|
472
|
-
child3.attachChild(root as any);
|
|
473
|
-
}).toThrow(/circular|cycle/i);
|
|
474
|
-
|
|
475
|
-
// Verify no corruption
|
|
476
|
-
verifyNoCycles(root);
|
|
477
|
-
verifyTreeMirror(root);
|
|
478
|
-
});
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
describe('Tree mirror invariant', () => {
|
|
482
|
-
it('should maintain 1:1 correspondence after operations', () => {
|
|
483
|
-
const root = new SimpleWorkflow('Root');
|
|
484
|
-
const child1 = new SimpleWorkflow('Child1', root);
|
|
485
|
-
const child2 = new SimpleWorkflow('Child2', root);
|
|
486
|
-
|
|
487
|
-
// Verify mirror after creation
|
|
488
|
-
verifyTreeMirror(root);
|
|
489
|
-
|
|
490
|
-
// Detach and reattach
|
|
491
|
-
root.detachChild(child1);
|
|
492
|
-
verifyTreeMirror(root);
|
|
493
|
-
|
|
494
|
-
root.attachChild(child1);
|
|
495
|
-
verifyTreeMirror(root);
|
|
496
|
-
|
|
497
|
-
// Verify both trees have same structure
|
|
498
|
-
expect(root.children.length).toBe(root.node.children.length);
|
|
499
|
-
expect(root.children[0].node).toBe(root.node.children[0]);
|
|
500
|
-
expect(root.children[1].node).toBe(root.node.children[1]);
|
|
501
|
-
});
|
|
502
|
-
|
|
503
|
-
it('should detect mirror violations', () => {
|
|
504
|
-
const parent = new SimpleWorkflow('Parent');
|
|
505
|
-
const child = new SimpleWorkflow('Child', parent);
|
|
506
|
-
|
|
507
|
-
// Manually corrupt node tree (simulating bug)
|
|
508
|
-
(child.node as any).parent = null;
|
|
509
|
-
|
|
510
|
-
// Should detect mirror violation
|
|
511
|
-
expect(() => {
|
|
512
|
-
verifyTreeMirror(parent);
|
|
513
|
-
}).toThrow(/MIRROR/);
|
|
514
|
-
});
|
|
515
|
-
});
|
|
516
|
-
|
|
517
|
-
describe('Single root invariant', () => {
|
|
518
|
-
it('should maintain exactly one root', () => {
|
|
519
|
-
const root = new SimpleWorkflow('Root');
|
|
520
|
-
const child1 = new SimpleWorkflow('Child1', root);
|
|
521
|
-
const child2 = new SimpleWorkflow('Child2', root);
|
|
522
|
-
|
|
523
|
-
// Count roots
|
|
524
|
-
const allNodes = collectAllNodes(root);
|
|
525
|
-
const roots = allNodes.filter(n => n.parent === null);
|
|
526
|
-
|
|
527
|
-
expect(roots.length).toBe(1);
|
|
528
|
-
expect(roots[0]).toBe(root);
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
it('should have one root after reparenting', () => {
|
|
532
|
-
const root1 = new SimpleWorkflow('Root1');
|
|
533
|
-
const root2 = new SimpleWorkflow('Root2');
|
|
534
|
-
const child = new SimpleWorkflow('Child', root1);
|
|
535
|
-
|
|
536
|
-
// Initially: 2 roots (root1 and root2)
|
|
537
|
-
let allNodes = [...collectAllNodes(root1), ...collectAllNodes(root2)];
|
|
538
|
-
let roots = allNodes.filter(n => n.parent === null);
|
|
539
|
-
expect(roots.length).toBe(2);
|
|
540
|
-
|
|
541
|
-
// Reparent child to root2
|
|
542
|
-
root1.detachChild(child);
|
|
543
|
-
root2.attachChild(child);
|
|
544
|
-
|
|
545
|
-
// Still: 2 roots (root1 and root2)
|
|
546
|
-
allNodes = [...collectAllNodes(root1), ...collectAllNodes(root2)];
|
|
547
|
-
roots = allNodes.filter(n => n.parent === null);
|
|
548
|
-
expect(roots.length).toBe(2);
|
|
549
|
-
});
|
|
550
|
-
});
|
|
551
|
-
|
|
552
|
-
describe('Connectedness invariant', () => {
|
|
553
|
-
it('should have all nodes reachable from root', () => {
|
|
554
|
-
const root = new SimpleWorkflow('Root');
|
|
555
|
-
const child1 = new SimpleWorkflow('Child1', root);
|
|
556
|
-
const child2 = new SimpleWorkflow('Child2', root);
|
|
557
|
-
const grandchild = new SimpleWorkflow('Grandchild', child1);
|
|
558
|
-
|
|
559
|
-
const allNodes = collectAllNodes(root);
|
|
560
|
-
const reachableFromRoot = new Set<Workflow>();
|
|
561
|
-
|
|
562
|
-
function traverse(node: Workflow): void {
|
|
563
|
-
reachableFromRoot.add(node);
|
|
564
|
-
node.children.forEach(traverse);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
traverse(root);
|
|
568
|
-
|
|
569
|
-
// All nodes should be reachable
|
|
570
|
-
allNodes.forEach(node => {
|
|
571
|
-
expect(reachableFromRoot.has(node)).toBe(true);
|
|
572
|
-
});
|
|
573
|
-
});
|
|
574
|
-
});
|
|
575
|
-
});
|
|
576
|
-
```
|
|
577
|
-
|
|
578
|
-
---
|
|
579
|
-
|
|
580
|
-
## Pattern 4: Adversarial Testing
|
|
581
|
-
|
|
582
|
-
```typescript
|
|
583
|
-
describe('Bidirectional Consistency: Adversarial Tests', () => {
|
|
584
|
-
describe('Manual mutation detection', () => {
|
|
585
|
-
it('should detect inconsistency from manual parent mutation', () => {
|
|
586
|
-
const parent1 = new SimpleWorkflow('Parent1');
|
|
587
|
-
const parent2 = new SimpleWorkflow('Parent2');
|
|
588
|
-
const child = new SimpleWorkflow('Child', parent1);
|
|
589
|
-
|
|
590
|
-
// Manually mutate parent (bypassing attachChild)
|
|
591
|
-
(child as any).parent = parent2;
|
|
592
|
-
|
|
593
|
-
// Should detect inconsistency
|
|
594
|
-
const errors = validateTreeConsistency(parent1);
|
|
595
|
-
|
|
596
|
-
expect(errors.length).toBeGreaterThan(0);
|
|
597
|
-
expect(errors.some(e => e.includes('Mismatched parent'))).toBe(true);
|
|
598
|
-
});
|
|
599
|
-
|
|
600
|
-
it('should detect inconsistency from manual children array mutation', () => {
|
|
601
|
-
const parent = new SimpleWorkflow('Parent');
|
|
602
|
-
const child = new SimpleWorkflow('Child', parent);
|
|
603
|
-
const other = new SimpleWorkflow('Other');
|
|
604
|
-
|
|
605
|
-
// Manually add to children array (bypassing attachChild)
|
|
606
|
-
(parent as any).children.push(other);
|
|
607
|
-
|
|
608
|
-
// Should detect inconsistency
|
|
609
|
-
const errors = validateTreeConsistency(parent);
|
|
610
|
-
|
|
611
|
-
expect(errors.length).toBeGreaterThan(0);
|
|
612
|
-
});
|
|
613
|
-
|
|
614
|
-
it('should detect inconsistency from node tree mutation', () => {
|
|
615
|
-
const parent = new SimpleWorkflow('Parent');
|
|
616
|
-
const child = new SimpleWorkflow('Child', parent);
|
|
617
|
-
|
|
618
|
-
// Manually mutate node tree
|
|
619
|
-
(child.node as any).parent = null;
|
|
620
|
-
|
|
621
|
-
// Should detect mirror violation
|
|
622
|
-
expect(() => {
|
|
623
|
-
verifyTreeMirror(parent);
|
|
624
|
-
}).toThrow();
|
|
625
|
-
});
|
|
626
|
-
});
|
|
627
|
-
|
|
628
|
-
describe('Stress testing', () => {
|
|
629
|
-
it('should maintain consistency with deep hierarchies', () => {
|
|
630
|
-
const root = new SimpleWorkflow('Root');
|
|
631
|
-
let current = root;
|
|
632
|
-
|
|
633
|
-
// Create 100 levels deep
|
|
634
|
-
for (let i = 0; i < 100; i++) {
|
|
635
|
-
const child = new SimpleWorkflow(`Level-${i}`);
|
|
636
|
-
current.attachChild(child);
|
|
637
|
-
current = child;
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
// Verify consistency at each level
|
|
641
|
-
verifyTreeMirror(root);
|
|
642
|
-
verifyNoCycles(root);
|
|
643
|
-
|
|
644
|
-
const errors = validateTreeConsistency(root);
|
|
645
|
-
expect(errors).toEqual([]);
|
|
646
|
-
});
|
|
647
|
-
|
|
648
|
-
it('should maintain consistency with wide hierarchies', () => {
|
|
649
|
-
const parent = new SimpleWorkflow('Parent');
|
|
650
|
-
const children: Workflow[] = [];
|
|
651
|
-
|
|
652
|
-
// Create 100 children
|
|
653
|
-
for (let i = 0; i < 100; i++) {
|
|
654
|
-
const child = new SimpleWorkflow(`Child-${i}`);
|
|
655
|
-
parent.attachChild(child);
|
|
656
|
-
children.push(child);
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
// Verify all children
|
|
660
|
-
children.forEach(child => {
|
|
661
|
-
verifyBidirectionalLink(parent, child);
|
|
662
|
-
});
|
|
663
|
-
|
|
664
|
-
// Verify tree mirror
|
|
665
|
-
verifyTreeMirror(parent);
|
|
666
|
-
|
|
667
|
-
const errors = validateTreeConsistency(parent);
|
|
668
|
-
expect(errors).toEqual([]);
|
|
669
|
-
});
|
|
670
|
-
|
|
671
|
-
it('should maintain consistency during rapid attach/detach cycles', () => {
|
|
672
|
-
const parent1 = new SimpleWorkflow('Parent1');
|
|
673
|
-
const parent2 = new SimpleWorkflow('Parent2');
|
|
674
|
-
const child = new SimpleWorkflow('Child', parent1);
|
|
675
|
-
|
|
676
|
-
// Rapid reparenting
|
|
677
|
-
for (let i = 0; i < 100; i++) {
|
|
678
|
-
if (i % 2 === 0) {
|
|
679
|
-
parent1.detachChild(child);
|
|
680
|
-
parent2.attachChild(child);
|
|
681
|
-
} else {
|
|
682
|
-
parent2.detachChild(child);
|
|
683
|
-
parent1.attachChild(child);
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
// Verify consistency after each cycle
|
|
687
|
-
const expectedParent = i % 2 === 0 ? parent2 : parent1;
|
|
688
|
-
expect(child.parent).toBe(expectedParent);
|
|
689
|
-
expect(child.node.parent).toBe(expectedParent.node);
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
// Final verification
|
|
693
|
-
verifyTreeMirror(parent1);
|
|
694
|
-
verifyTreeMirror(parent2);
|
|
695
|
-
});
|
|
696
|
-
});
|
|
697
|
-
});
|
|
698
|
-
```
|
|
699
|
-
|
|
700
|
-
---
|
|
701
|
-
|
|
702
|
-
## Pattern 5: Property-Based Testing
|
|
703
|
-
|
|
704
|
-
```typescript
|
|
705
|
-
describe('Bidirectional Consistency: Property-Based Tests', () => {
|
|
706
|
-
it('should satisfy round-trip property', () => {
|
|
707
|
-
const root = new SimpleWorkflow('Root');
|
|
708
|
-
const child1 = new SimpleWorkflow('Child1', root);
|
|
709
|
-
const child2 = new SimpleWorkflow('Child2', root);
|
|
710
|
-
|
|
711
|
-
// Capture initial state
|
|
712
|
-
const initialChildren = [...root.children];
|
|
713
|
-
const initialNodeChildren = [...root.node.children];
|
|
714
|
-
|
|
715
|
-
// Detach and reattach
|
|
716
|
-
root.detachChild(child1);
|
|
717
|
-
root.attachChild(child1);
|
|
718
|
-
|
|
719
|
-
// Should return to equivalent state
|
|
720
|
-
expect(root.children).toEqual(initialChildren);
|
|
721
|
-
expect(root.node.children).toEqual(initialNodeChildren);
|
|
722
|
-
|
|
723
|
-
verifyTreeMirror(root);
|
|
724
|
-
});
|
|
725
|
-
|
|
726
|
-
it('should satisfy idempotence property', () => {
|
|
727
|
-
const parent = new SimpleWorkflow('Parent');
|
|
728
|
-
const child = new SimpleWorkflow('Child', parent);
|
|
729
|
-
|
|
730
|
-
// Already attached - should not change state
|
|
731
|
-
parent.attachChild(child);
|
|
732
|
-
|
|
733
|
-
expect(parent.children).toEqual([child]);
|
|
734
|
-
expect(parent.node.children).toEqual([child.node]);
|
|
735
|
-
|
|
736
|
-
verifyTreeMirror(parent);
|
|
737
|
-
});
|
|
738
|
-
|
|
739
|
-
it('should satisfy commutativity property for siblings', () => {
|
|
740
|
-
const parent = new SimpleWorkflow('Parent');
|
|
741
|
-
const child1 = new SimpleWorkflow('Child1');
|
|
742
|
-
const child2 = new SimpleWorkflow('Child2');
|
|
743
|
-
const child3 = new SimpleWorkflow('Child3');
|
|
744
|
-
|
|
745
|
-
// Attach in order 1, 2, 3
|
|
746
|
-
parent.attachChild(child1);
|
|
747
|
-
parent.attachChild(child2);
|
|
748
|
-
parent.attachChild(child3);
|
|
749
|
-
|
|
750
|
-
const structure1 = [...parent.children];
|
|
751
|
-
|
|
752
|
-
// Clean up
|
|
753
|
-
parent.detachChild(child1);
|
|
754
|
-
parent.detachChild(child2);
|
|
755
|
-
parent.detachChild(child3);
|
|
756
|
-
|
|
757
|
-
// Attach in order 3, 2, 1
|
|
758
|
-
parent.attachChild(child3);
|
|
759
|
-
parent.attachChild(child2);
|
|
760
|
-
parent.attachChild(child1);
|
|
761
|
-
|
|
762
|
-
const structure2 = [...parent.children];
|
|
763
|
-
|
|
764
|
-
// Same children (order may differ)
|
|
765
|
-
expect(structure1.sort()).toEqual(structure2.sort());
|
|
766
|
-
|
|
767
|
-
verifyTreeMirror(parent);
|
|
768
|
-
});
|
|
769
|
-
});
|
|
770
|
-
```
|
|
771
|
-
|
|
772
|
-
---
|
|
773
|
-
|
|
774
|
-
## Pattern 6: Integration with WorkflowTreeDebugger
|
|
775
|
-
|
|
776
|
-
```typescript
|
|
777
|
-
describe('Bidirectional Consistency: Debugger Integration', () => {
|
|
778
|
-
it('should verify consistency using WorkflowTreeDebugger', () => {
|
|
779
|
-
const parent = new SimpleWorkflow('Parent');
|
|
780
|
-
const child1 = new SimpleWorkflow('Child1', parent);
|
|
781
|
-
const child2 = new SimpleWorkflow('Child2', parent);
|
|
782
|
-
|
|
783
|
-
const debugger = new WorkflowTreeDebugger(parent);
|
|
784
|
-
|
|
785
|
-
// Verify debugger can find all nodes
|
|
786
|
-
expect(debugger.getNode(parent.id)).toBeDefined();
|
|
787
|
-
expect(debugger.getNode(child1.id)).toBeDefined();
|
|
788
|
-
expect(debugger.getNode(child2.id)).toBeDefined();
|
|
789
|
-
|
|
790
|
-
// Verify debugger tree structure
|
|
791
|
-
const tree = debugger.getTree();
|
|
792
|
-
expect(tree.name).toBe('Parent');
|
|
793
|
-
expect(tree.children.length).toBe(2);
|
|
794
|
-
expect(tree.children[0].name).toBe('Child1');
|
|
795
|
-
expect(tree.children[1].name).toBe('Child2');
|
|
796
|
-
|
|
797
|
-
// Verify stats
|
|
798
|
-
const stats = debugger.getStats();
|
|
799
|
-
expect(stats.totalNodes).toBe(3);
|
|
800
|
-
});
|
|
801
|
-
|
|
802
|
-
it('should maintain consistency after operations visible to debugger', () => {
|
|
803
|
-
const parent1 = new SimpleWorkflow('Parent1');
|
|
804
|
-
const parent2 = new SimpleWorkflow('Parent2');
|
|
805
|
-
const child = new SimpleWorkflow('Child', parent1);
|
|
806
|
-
|
|
807
|
-
const debugger1 = new WorkflowTreeDebugger(parent1);
|
|
808
|
-
|
|
809
|
-
// Verify initial state
|
|
810
|
-
expect(debugger1.getTree().children.length).toBe(1);
|
|
811
|
-
|
|
812
|
-
// Reparent
|
|
813
|
-
parent1.detachChild(child);
|
|
814
|
-
parent2.attachChild(child);
|
|
815
|
-
|
|
816
|
-
// Old parent's debugger should show empty tree
|
|
817
|
-
expect(debugger1.getTree().children.length).toBe(0);
|
|
818
|
-
|
|
819
|
-
// New parent's debugger should show child
|
|
820
|
-
const debugger2 = new WorkflowTreeDebugger(parent2);
|
|
821
|
-
expect(debugger2.getTree().children.length).toBe(1);
|
|
822
|
-
expect(debugger2.getTree().children[0].name).toBe('Child');
|
|
823
|
-
|
|
824
|
-
// Verify consistency
|
|
825
|
-
verifyTreeMirror(parent1);
|
|
826
|
-
verifyTreeMirror(parent2);
|
|
827
|
-
});
|
|
828
|
-
|
|
829
|
-
it('should generate correct tree string representation', () => {
|
|
830
|
-
const root = new SimpleWorkflow('Root');
|
|
831
|
-
const child1 = new SimpleWorkflow('Child1', root);
|
|
832
|
-
const child2 = new SimpleWorkflow('Child2', root);
|
|
833
|
-
|
|
834
|
-
const debugger = new WorkflowTreeDebugger(root);
|
|
835
|
-
const treeString = debugger.toTreeString();
|
|
836
|
-
|
|
837
|
-
// Verify tree structure in ASCII
|
|
838
|
-
expect(treeString).toContain('Root');
|
|
839
|
-
expect(treeString).toContain('Child1');
|
|
840
|
-
expect(treeString).toContain('Child2');
|
|
841
|
-
expect(treeString).toContain('├──'); // Tree connector
|
|
842
|
-
expect(treeString).toContain('└──'); // Tree connector
|
|
843
|
-
});
|
|
844
|
-
});
|
|
845
|
-
```
|
|
846
|
-
|
|
847
|
-
---
|
|
848
|
-
|
|
849
|
-
## Test File Template
|
|
850
|
-
|
|
851
|
-
```typescript
|
|
852
|
-
/**
|
|
853
|
-
* Template for bidirectional consistency tests
|
|
854
|
-
* Copy and modify for your specific test scenario
|
|
855
|
-
*/
|
|
856
|
-
|
|
857
|
-
import { describe, it, expect } from 'vitest';
|
|
858
|
-
import { Workflow } from '../../index.js';
|
|
859
|
-
import {
|
|
860
|
-
verifyBidirectionalLink,
|
|
861
|
-
verifyTreeMirror,
|
|
862
|
-
verifyOrphaned,
|
|
863
|
-
verifyNoCycles,
|
|
864
|
-
validateTreeConsistency,
|
|
865
|
-
collectAllNodes,
|
|
866
|
-
} from '../helpers/tree-verification';
|
|
867
|
-
|
|
868
|
-
class TestWorkflow extends Workflow {
|
|
869
|
-
async run(): Promise<string> {
|
|
870
|
-
return 'done';
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
describe('YOUR TEST SUITE NAME', () => {
|
|
875
|
-
it('should describe the test scenario', () => {
|
|
876
|
-
// ============================================================
|
|
877
|
-
// ARRANGE: Set up test data
|
|
878
|
-
// ============================================================
|
|
879
|
-
const parent = new TestWorkflow('Parent');
|
|
880
|
-
const child = new TestWorkflow('Child');
|
|
881
|
-
|
|
882
|
-
// ============================================================
|
|
883
|
-
// ACT: Execute the behavior
|
|
884
|
-
// ============================================================
|
|
885
|
-
parent.attachChild(child);
|
|
886
|
-
|
|
887
|
-
// ============================================================
|
|
888
|
-
// ASSERT: Verify the result
|
|
889
|
-
// ============================================================
|
|
890
|
-
|
|
891
|
-
// 1. Verify bidirectional links
|
|
892
|
-
verifyBidirectionalLink(parent, child);
|
|
893
|
-
|
|
894
|
-
// 2. Verify tree mirror invariant
|
|
895
|
-
verifyTreeMirror(parent);
|
|
896
|
-
|
|
897
|
-
// 3. Verify no inconsistencies
|
|
898
|
-
const errors = validateTreeConsistency(parent);
|
|
899
|
-
expect(errors).toEqual([]);
|
|
900
|
-
|
|
901
|
-
// 4. Add specific assertions for your scenario
|
|
902
|
-
expect(child.parent).toBe(parent);
|
|
903
|
-
expect(parent.children).toContain(child);
|
|
904
|
-
expect(child.node.parent).toBe(parent.node);
|
|
905
|
-
expect(parent.node.children).toContain(child.node);
|
|
906
|
-
});
|
|
907
|
-
|
|
908
|
-
it('should test error case', () => {
|
|
909
|
-
const parent1 = new TestWorkflow('Parent1');
|
|
910
|
-
const parent2 = new TestWorkflow('Parent2');
|
|
911
|
-
const child = new TestWorkflow('Child', parent1);
|
|
912
|
-
|
|
913
|
-
// Should throw
|
|
914
|
-
expect(() => {
|
|
915
|
-
parent2.attachChild(child);
|
|
916
|
-
}).toThrow(/already has a parent/);
|
|
917
|
-
|
|
918
|
-
// Verify no corruption occurred
|
|
919
|
-
verifyBidirectionalLink(parent1, child);
|
|
920
|
-
verifyTreeMirror(parent1);
|
|
921
|
-
|
|
922
|
-
const errors = validateTreeConsistency(parent1);
|
|
923
|
-
expect(errors).toEqual([]);
|
|
924
|
-
});
|
|
925
|
-
});
|
|
926
|
-
```
|
|
927
|
-
|
|
928
|
-
---
|
|
929
|
-
|
|
930
|
-
## Usage Guidelines
|
|
931
|
-
|
|
932
|
-
### 1. Always Test Both Trees
|
|
933
|
-
|
|
934
|
-
```typescript
|
|
935
|
-
// BAD: Only tests workflow tree
|
|
936
|
-
expect(child.parent).toBe(parent);
|
|
937
|
-
expect(parent.children).toContain(child);
|
|
938
|
-
|
|
939
|
-
// GOOD: Tests both trees
|
|
940
|
-
expect(child.parent).toBe(parent);
|
|
941
|
-
expect(parent.children).toContain(child);
|
|
942
|
-
expect(child.node.parent).toBe(parent.node);
|
|
943
|
-
expect(parent.node.children).toContain(child.node);
|
|
944
|
-
|
|
945
|
-
// BETTER: Use helper
|
|
946
|
-
verifyBidirectionalLink(parent, child);
|
|
947
|
-
```
|
|
948
|
-
|
|
949
|
-
### 2. Run Consistency Checks After Operations
|
|
950
|
-
|
|
951
|
-
```typescript
|
|
952
|
-
// After attach/detach/reparenting
|
|
953
|
-
parent.attachChild(child);
|
|
954
|
-
|
|
955
|
-
// Always verify
|
|
956
|
-
verifyTreeMirror(parent);
|
|
957
|
-
expect(validateTreeConsistency(parent)).toEqual([]);
|
|
958
|
-
```
|
|
959
|
-
|
|
960
|
-
### 3. Test Error Cases Don't Corrupt State
|
|
961
|
-
|
|
962
|
-
```typescript
|
|
963
|
-
expect(() => {
|
|
964
|
-
parent2.attachChild(child); // Should throw
|
|
965
|
-
}).toThrow();
|
|
966
|
-
|
|
967
|
-
// Verify state unchanged
|
|
968
|
-
verifyBidirectionalLink(parent1, child);
|
|
969
|
-
verifyTreeMirror(parent1);
|
|
970
|
-
```
|
|
971
|
-
|
|
972
|
-
### 4. Use Descriptive Test Names
|
|
973
|
-
|
|
974
|
-
```typescript
|
|
975
|
-
// Good
|
|
976
|
-
it('should maintain bidirectional consistency after reparenting', () => {});
|
|
977
|
-
|
|
978
|
-
// Bad
|
|
979
|
-
it('should work', () => {});
|
|
980
|
-
```
|
|
981
|
-
|
|
982
|
-
### 5. Add Comments for Complex Scenarios
|
|
983
|
-
|
|
984
|
-
```typescript
|
|
985
|
-
it('should handle reparenting of deep hierarchies', () => {
|
|
986
|
-
// Create: Root -> Mid1 -> Leaf
|
|
987
|
-
const root = new TestWorkflow('Root');
|
|
988
|
-
const mid1 = new TestWorkflow('Mid1', root);
|
|
989
|
-
const leaf = new TestWorkflow('Leaf', mid1);
|
|
990
|
-
|
|
991
|
-
// Create: Root2 -> Mid2
|
|
992
|
-
const root2 = new TestWorkflow('Root2');
|
|
993
|
-
const mid2 = new TestWorkflow('Mid2', root2);
|
|
994
|
-
|
|
995
|
-
// Reparent: Move Mid1 (and its child Leaf) from Root to Root2
|
|
996
|
-
root.detachChild(mid1);
|
|
997
|
-
root2.attachChild(mid1);
|
|
998
|
-
|
|
999
|
-
// Expected structure:
|
|
1000
|
-
// - Root2 -> Mid2
|
|
1001
|
-
// -> Mid1 -> Leaf
|
|
1002
|
-
// - Root (empty)
|
|
1003
|
-
|
|
1004
|
-
verifyTreeMirror(root2);
|
|
1005
|
-
expect(root2.children).toEqual([mid2, mid1]);
|
|
1006
|
-
expect(mid1.children).toEqual([leaf]);
|
|
1007
|
-
});
|
|
1008
|
-
```
|
|
1009
|
-
|
|
1010
|
-
---
|
|
1011
|
-
|
|
1012
|
-
**Document Status:** Complete
|
|
1013
|
-
**Ready for Use:** Yes
|
|
1014
|
-
**Maintainer:** P1M3T1S4 Research Team
|