groundswell 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/subtask-planning/prp-base-create.md +120 -0
- package/.claude/commands/subtask-planning/prp-base-execute.md +65 -0
- package/.claude/commands/task-breakdown.md +94 -0
- package/.claude/system_prompts/task-breakdown.md +1 -0
- package/CHANGELOG.md +188 -0
- package/PRD.md +543 -0
- package/README.md +99 -5
- package/examples/README.md +15 -1
- package/examples/examples/11-reparenting-workflows.ts +269 -0
- package/examples/index.ts +4 -0
- package/package-lock.json +2398 -0
- package/package.json +3 -1
- package/plan/001_d3bb02af4886/TEST_RESULTS.md +259 -0
- package/plan/001_d3bb02af4886/bug_fix_tasks.json +484 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S1/PRP.md +488 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S2/PRP.md +581 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S3/PRP.md +687 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S1/PRP.md +492 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/PRP.md +932 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/concurrent_error_testing_patterns.md +1109 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/vitest_concurrent_testing.md +802 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/workflow_engine_test_references.md +603 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S1/PRP.md +564 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S3/PRP.md +518 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S4/PRP.md +1252 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/PRP.md +364 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/CODEBASE_INVENTORY.md +114 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/DECORATOR_DOCUMENTATION_PATTERNS.md +205 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/PRD_LOCATION_ANALYSIS.md +199 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/ULTRATHINK_PRP_PLAN.md +134 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/PRP.md +495 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/research/console_error_inventory.md +435 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S2/PRP.md +506 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S3/PRP.md +612 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/PRP.md +558 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/research/external_research.md +788 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S2/PRP.md +460 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S3/PRP.md +454 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/PRP.md +520 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/RECOMMENDATION.md +417 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/external_workflow_engines_research.md +760 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/security_implications_analysis.md +245 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S2/PRP.md +792 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/PRP.md +535 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/TEST_EXECUTION_REPORT.md +190 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/PRP.md +654 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/TEST_FIX_REPORT.md +227 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/KEY_FINDINGS.md +345 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/QUICK_REFERENCE.md +193 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/test_maintenance_research.md +1323 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/BREAKING_CHANGES_AUDIT.md +1011 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/PRP.md +927 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S2/PRP.md +505 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/architecture/logger_child_signature_analysis.md +401 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/child_implementation_research.md +142 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/test_patterns_research.md +112 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/vitest_patterns_research.md +159 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/PRP.md +549 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/VERIFICATION_REPORT.md +368 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/edge_case_analysis.md +172 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/usage_inventory.md +175 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S2/PRP.md +696 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S4/PRP.md +860 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/PRP.md +1066 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01-testing-aggregated-errors.md +1103 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01_typescript_error_aggregation_patterns.md +789 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02-error-merge-strategy-testing-guide.md +1098 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02_aggregate_error_patterns.md +1037 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03-promise-allsettled-testing-patterns.md +916 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03_error_merging_strategies.md +1045 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/04_github_stackoverflow_examples.md +890 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/05_comprehensive_summary.md +822 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/INDEX.md +668 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/QUICK_REFERENCE.md +706 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/README.md +265 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/RESEARCH_REPORT.md +655 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S4/research/vitest_testing_patterns.md +1103 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T3S2/PRP.md +426 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/PRP.md +506 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/QUICK_REFERENCE.md +114 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/RESEARCH_SUMMARY.md +316 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/vitest_observer_error_logging_best_practices.md +754 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S3/PRP.md +612 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/PRP.md +719 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/README.md +215 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/analysis.md +765 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S3/PRP.md +718 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/DECISION.md +149 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/PRP.md +470 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/ULTRATHINK_PLAN.md +332 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/codebase_workflow_name_analysis.md +167 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/external_best_practices.md +265 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/validation_patterns.md +273 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S1/workflow_engine_ancestry_api_research.md +760 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S3-PRP.md +434 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S1/PRP.md +717 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/PRP.md +472 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/VALIDATION_REPORT.md +125 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/research/ULTRATHINK_PRP_PLAN.md +301 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/error-logging-best-practices.md +1170 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/research_typescript_partial_and_overloads.md +940 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-quick-reference.md +151 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-research.md +650 -0
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/prd_snapshot.md +259 -0
- package/plan/001_d3bb02af4886/bugfix/P1M1T1S1/PRP.md +457 -0
- package/plan/001_d3bb02af4886/bugfix/RESEARCH_SUMMARY.md +346 -0
- package/plan/001_d3bb02af4886/bugfix/architecture/codebase_structure.md +311 -0
- package/plan/001_d3bb02af4886/bugfix/architecture/concurrent_execution_best_practices.md +1565 -0
- package/plan/001_d3bb02af4886/bugfix/architecture/error_handling_patterns.md +288 -0
- package/plan/001_d3bb02af4886/bugfix/architecture/promise_all_analysis.md +741 -0
- package/plan/001_d3bb02af4886/docs/PRP/P1M1T1S4-functional-workflow-error-state-capture-test.md +652 -0
- package/plan/001_d3bb02af4886/docs/PRP/PRP.md +527 -0
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S1-PRP.md +415 -0
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S2-PRP.md +378 -0
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S4-PRP.md +713 -0
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M2T1S4-PRP.md +370 -0
- package/plan/001_d3bb02af4886/docs/PRP_P1M3T1S3.md +499 -0
- package/plan/001_d3bb02af4886/docs/TEST_RESULTS.md +230 -0
- package/plan/001_d3bb02af4886/docs/bugfix/ANALYSIS_PRD_VS_IMPLEMENTATION.md +1134 -0
- package/plan/001_d3bb02af4886/docs/bugfix/GAP_ANALYSIS_SUMMARY.md +179 -0
- package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/PRP.md +629 -0
- package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/validation-report.md +214 -0
- package/plan/001_d3bb02af4886/docs/bugfix/PRP_P1M4T2S3.md +629 -0
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_PRP.md +529 -0
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_QUICK_REFERENCE.md +142 -0
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_README.md +304 -0
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_TEST_RESULTS.md +558 -0
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_VALIDATION_SUMMARY.md +256 -0
- package/plan/001_d3bb02af4886/docs/bugfix/system_context.md +346 -0
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/bug_analysis.md +415 -0
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/implementation_patterns.md +489 -0
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/system_context.md +218 -0
- package/plan/001_d3bb02af4886/docs/bugfix_INITIATION_SUMMARY.md +380 -0
- package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_PATTERNS.md +1923 -0
- package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_QUICK_REF.md +319 -0
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/codebase-context.md +115 -0
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/cycle-detection-algorithms.md +134 -0
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/test-patterns.md +153 -0
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/workflow-class.md +132 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_BEST_PRACTICES.md +716 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_QUICK_REF.md +186 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/GROUNDSWELL_DECORATOR_EXAMPLES.md +604 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/INDEX.md +213 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/codebase_structure.md +30 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/existing_test_pattern.md +56 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/getRootObservers_implementation.md +53 -0
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/test_conventions.md +49 -0
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/PRP.md +958 -0
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/QUICK_REFERENCE.md +339 -0
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/README.md +305 -0
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/SUMMARY.md +433 -0
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/bidirectional-tree-consistency-testing.md +1574 -0
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/test-pattern-examples.md +1014 -0
- package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_QUICK_REF.md +376 -0
- package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_RESEARCH.md +1507 -0
- package/plan/001_d3bb02af4886/docs/research/bugfix_typescript_patterns.md +949 -0
- package/plan/001_d3bb02af4886/docs/research/error-testing-research.md +619 -0
- package/plan/001_d3bb02af4886/docs/research/error_handling_patterns.md +723 -0
- package/plan/{research → 001_d3bb02af4886/docs/research/general}/introspection-security-guide.md +56 -0
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/PRP_TEMPLATE.md +460 -0
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/QUICK_REFERENCE.md +324 -0
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/README.md +175 -0
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/RESEARCH_REPORT.md +499 -0
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/SUMMARY.md +163 -0
- package/plan/bugfix/BUG_FIX_SUMMARY.md +961 -0
- package/src/__tests__/adversarial/attachChild-performance.test.ts +216 -0
- package/src/__tests__/adversarial/circular-reference.test.ts +101 -0
- package/src/__tests__/adversarial/complex-circular-reference.test.ts +139 -0
- package/src/__tests__/adversarial/concurrent-task-failures.test.ts +571 -0
- package/src/__tests__/adversarial/deep-analysis.test.ts +729 -0
- package/src/__tests__/adversarial/deep-hierarchy-stress.test.ts +213 -0
- package/src/__tests__/adversarial/e2e-prd-validation.test.ts +448 -0
- package/src/__tests__/adversarial/edge-case.test.ts +703 -0
- package/src/__tests__/adversarial/error-merge-strategy.test.ts +760 -0
- package/src/__tests__/adversarial/incremental-performance.test.ts +140 -0
- package/src/__tests__/adversarial/node-map-update-benchmarks.test.ts +457 -0
- package/src/__tests__/adversarial/observer-propagation.test.ts +487 -0
- package/src/__tests__/adversarial/parent-validation.test.ts +143 -0
- package/src/__tests__/adversarial/prd-12-2-compliance.test.ts +611 -0
- package/src/__tests__/adversarial/prd-compliance.test.ts +731 -0
- package/src/__tests__/compatibility/backward-compatibility.test.ts +1572 -0
- package/src/__tests__/helpers/index.ts +18 -0
- package/src/__tests__/helpers/tree-verification.ts +257 -0
- package/src/__tests__/integration/bidirectional-consistency.test.ts +847 -0
- package/src/__tests__/integration/observer-logging.test.ts +643 -0
- package/src/__tests__/integration/tree-mirroring.test.ts +37 -0
- package/src/__tests__/integration/workflow-reparenting.test.ts +303 -0
- package/src/__tests__/unit/context.test.ts +79 -0
- package/src/__tests__/unit/logger.test.ts +293 -0
- package/src/__tests__/unit/observable.test.ts +321 -0
- package/src/__tests__/unit/tree-debugger-incremental.test.ts +170 -0
- package/src/__tests__/unit/utils/workflow-error-utils.test.ts +209 -0
- package/src/__tests__/unit/workflow-detachChild.test.ts +100 -0
- package/src/__tests__/unit/workflow-emitEvent-childDetached.test.ts +153 -0
- package/src/__tests__/unit/workflow-isDescendantOf.test.ts +180 -0
- package/src/__tests__/unit/workflow.test.ts +277 -1
- package/src/core/agent.ts +21 -1
- package/src/core/logger.ts +27 -2
- package/src/core/workflow-context.ts +6 -4
- package/src/core/workflow.ts +252 -14
- package/src/debugger/tree-debugger.ts +52 -7
- package/src/decorators/task.ts +65 -2
- package/src/index.ts +4 -2
- package/src/types/decorators.ts +8 -1
- package/src/types/events.ts +1 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/observable.ts +32 -3
- package/src/utils/workflow-error-utils.ts +56 -0
- package/tsconfig.json +1 -1
- package/llms_full.txt +0 -5890
- package/tasks.json +0 -0
- /package/plan/{backlog.json → 001_d3bb02af4886/backlog.json} +0 -0
- /package/plan/{P1P2/PRP.md → 001_d3bb02af4886/docs/PRP/P1P2-PRP.md} +0 -0
- /package/plan/{P3P4/PRP.md → 001_d3bb02af4886/docs/PRP/P3P4-PRP.md} +0 -0
- /package/plan/{P4P5/PRP.md → 001_d3bb02af4886/docs/PRP/P4P5-PRP.md} +0 -0
- /package/plan/{architecture → 001_d3bb02af4886/docs/architecture}/external_deps.md +0 -0
- /package/plan/{architecture → 001_d3bb02af4886/docs/architecture}/system_context.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/LRU_CACHE_BEST_PRACTICES.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/LRU_CACHE_CODE_PATTERNS.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/LRU_CACHE_INTEGRATION_GUIDE.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/LRU_CACHE_RESEARCH_INDEX.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/REFLECTION_INDEX.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/REFLECTION_RESEARCH_REPORT.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/RESEARCH_SUMMARY.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/anthropic-sdk.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/async-local-storage.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-code-patterns.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-decision-matrix.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-implementation-guide.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-integration-guide.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-patterns.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/reflection-quick-reference.md +0 -0
- /package/plan/{P1P2/research → 001_d3bb02af4886/docs/research/P1P2}/zod-schema.md +0 -0
- /package/plan/{P3P4/research → 001_d3bb02af4886/docs/research/P3P4}/caching-lru.md +0 -0
- /package/plan/{P3P4/research → 001_d3bb02af4886/docs/research/P3P4}/introspection-tools.md +0 -0
- /package/plan/{P3P4/research → 001_d3bb02af4886/docs/research/P3P4}/reflection-patterns.md +0 -0
- /package/plan/{P4P5/research → 001_d3bb02af4886/docs/research/P4P5}/RESEARCH_SUMMARY.md +0 -0
- /package/plan/{research → 001_d3bb02af4886/docs/research/general}/INTROSPECTION_RESEARCH_SUMMARY.md +0 -0
- /package/plan/{research → 001_d3bb02af4886/docs/research/general}/README-INTROSPECTION.md +0 -0
- /package/plan/{research → 001_d3bb02af4886/docs/research/general}/agent-introspection-patterns.md +0 -0
- /package/plan/{research → 001_d3bb02af4886/docs/research/general}/introspection-tool-examples.md +0 -0
- /package/{PRPs/PRDs/001-hierarchical-workflow-engine.md → plan/001_d3bb02af4886/prd_snapshot.md} +0 -0
|
@@ -0,0 +1,612 @@
|
|
|
1
|
+
# PRP: Add Tests for Observer Error Logging (P1.M3.T1.S3)
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
**Feature Goal**: Add comprehensive test suite for observer error logging to verify that observer errors are logged through `WorkflowLogger` instead of `console.error`, errors don't crash workflow execution, and error context is properly captured.
|
|
6
|
+
|
|
7
|
+
**Deliverable**: Enhanced test suite at `src/__tests__/integration/observer-logging.test.ts` with comprehensive coverage of all observer error scenarios.
|
|
8
|
+
|
|
9
|
+
**Success Definition**:
|
|
10
|
+
- All observer callback errors (onLog, onEvent, onStateUpdated, onTreeChanged) are tested
|
|
11
|
+
- Tests verify errors are logged to `workflow.node.logs` (structured logging)
|
|
12
|
+
- Tests verify workflow execution continues despite observer errors
|
|
13
|
+
- Tests verify error context is captured in log entries
|
|
14
|
+
- All tests pass: `uv run vitest run src/__tests__/integration/observer-logging.test.ts`
|
|
15
|
+
|
|
16
|
+
## Why
|
|
17
|
+
|
|
18
|
+
- **Verification of S2 Implementation**: S2 replaced `console.error` with `logger.error` for observer errors. S3 adds tests to verify this change works correctly.
|
|
19
|
+
- **Regression Prevention**: Tests ensure future changes don't break observer error handling
|
|
20
|
+
- **Observable Error Behavior**: Observer errors should be isolated - one throwing observer shouldn't crash the workflow or prevent other observers from being notified
|
|
21
|
+
- **Debugging Capability**: Structured error logs with context (error object, event type, node ID) are essential for debugging observer issues in production
|
|
22
|
+
|
|
23
|
+
## What
|
|
24
|
+
|
|
25
|
+
Add comprehensive tests for observer error logging covering:
|
|
26
|
+
|
|
27
|
+
1. **Error Logging Verification**: Verify observer errors go to `WorkflowLogger` (captured in `workflow.node.logs`), not `console.error`
|
|
28
|
+
2. **Error Isolation**: Verify workflow execution continues when observers throw errors
|
|
29
|
+
3. **Error Context**: Verify log entries contain error context (error object, event type, node ID)
|
|
30
|
+
4. **Infinite Recursion Prevention**: Verify `onLog` errors don't cause infinite loops
|
|
31
|
+
5. **Multiple Observers**: Verify other observers continue to be notified after one throws
|
|
32
|
+
|
|
33
|
+
### Success Criteria
|
|
34
|
+
|
|
35
|
+
- [ ] Tests verify all four observer callbacks (onLog, onEvent, onStateUpdated, onTreeChanged) error handling
|
|
36
|
+
- [ ] Tests verify errors are logged with structured data (error object, context)
|
|
37
|
+
- [ ] Tests verify workflow execution continues after observer errors
|
|
38
|
+
- [ ] Tests verify `console.error` is NOT called for observer execution errors (validation errors still use console.error)
|
|
39
|
+
- [ ] All existing tests continue to pass
|
|
40
|
+
- [ ] Test coverage is comprehensive for edge cases
|
|
41
|
+
|
|
42
|
+
## All Needed Context
|
|
43
|
+
|
|
44
|
+
### Context Completeness Check
|
|
45
|
+
|
|
46
|
+
_Before writing this PRP, validate: "If someone knew nothing about this codebase, would they have everything needed to implement this successfully?"_
|
|
47
|
+
|
|
48
|
+
**Answer**: Yes. This PRP provides complete context including existing test patterns, observer implementation details, exact file locations, and specific test patterns to follow.
|
|
49
|
+
|
|
50
|
+
### Documentation & References
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
# MUST READ - Implementation context from S2
|
|
54
|
+
- file: plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S2/PRP.md
|
|
55
|
+
why: Understand the observer error handling implementation that S2 completed
|
|
56
|
+
critical: S2 replaced console.error with logger.error for all observer execution errors
|
|
57
|
+
section: Full PRP - especially Implementation Blueprint section
|
|
58
|
+
|
|
59
|
+
# Observer error handling implementation
|
|
60
|
+
- file: src/core/workflow.ts
|
|
61
|
+
why: Observer error handling implementation - lines 368-378 (onEvent), 390-396 (onStateUpdated)
|
|
62
|
+
pattern: try-catch blocks with this.logger.error() calls including error context
|
|
63
|
+
gotcha: onTreeChanged is called inside onEvent's try-catch, so errors are logged as "Observer onEvent error"
|
|
64
|
+
|
|
65
|
+
- file: src/core/logger.ts
|
|
66
|
+
why: WorkflowLogger implementation with emitWithoutObserverNotification for infinite recursion prevention
|
|
67
|
+
pattern: Lines 34-45 show onLog error handling creating error log entry
|
|
68
|
+
critical: Uses emitWithoutObserverNotification() to prevent infinite recursion when observer.onLog() throws
|
|
69
|
+
|
|
70
|
+
# Existing test file (comprehensive, may need enhancement)
|
|
71
|
+
- file: src/__tests__/integration/observer-logging.test.ts
|
|
72
|
+
why: Existing observer error logging tests created in S2 - use as pattern reference
|
|
73
|
+
pattern: Integration test structure, vi.spyOn for mocking, expect assertions on workflow.node.logs
|
|
74
|
+
gotcha: This file was created in S2 (commit c572b41) - verify it covers all scenarios
|
|
75
|
+
|
|
76
|
+
# Test framework configuration
|
|
77
|
+
- file: vitest.config.ts
|
|
78
|
+
why: Test configuration - vitest with globals enabled, includes src/__tests__/**/*.test.ts
|
|
79
|
+
pattern: Test file naming convention *.test.ts in src/__tests__/ directory
|
|
80
|
+
|
|
81
|
+
# Observer interface
|
|
82
|
+
- file: src/types/observer.ts
|
|
83
|
+
why: WorkflowObserver interface definition - all four callback methods
|
|
84
|
+
pattern: onLog, onEvent, onStateUpdated, onTreeChanged methods
|
|
85
|
+
|
|
86
|
+
# Test patterns reference
|
|
87
|
+
- file: src/__tests__/unit/logger.test.ts
|
|
88
|
+
why: Pattern for testing logger behavior - verify logs go to workflow.node.logs
|
|
89
|
+
pattern: expect(workflow.node.logs.length).toBe(n), expect(workflow.node.logs[x].message).toBe('...')
|
|
90
|
+
|
|
91
|
+
- file: src/__tests__/unit/observable.test.ts
|
|
92
|
+
why: Pattern for testing Observable class error handling with mock logger
|
|
93
|
+
pattern: const mockLogger = { error: vi.fn() }; expect(mockLogger.error).toHaveBeenCalledWith(...)
|
|
94
|
+
|
|
95
|
+
# Architecture documentation
|
|
96
|
+
- file: plan/001_d3bb02af4886/bugfix/architecture/codebase_structure.md
|
|
97
|
+
why: Section 9 (Testing Strategy) outlines vitest test patterns
|
|
98
|
+
section: Lines 270-286
|
|
99
|
+
|
|
100
|
+
# External documentation
|
|
101
|
+
- url: https://vitest.dev/api/expect.html#tothrow
|
|
102
|
+
why: Vitest assertions for testing error throwing behavior
|
|
103
|
+
critical: toThrow(), not.toThrow(), resolves, rejects patterns
|
|
104
|
+
|
|
105
|
+
- url: https://vitest.dev/guide/mocking.html#spy-on
|
|
106
|
+
why: Mocking console.error to verify it's NOT called for observer errors
|
|
107
|
+
pattern: vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
108
|
+
|
|
109
|
+
- url: https://vitest.dev/api/expect.html#tobedefined
|
|
110
|
+
why: Assertions for verifying error log entries exist
|
|
111
|
+
critical: toBeDefined(), toEqual(), toHaveProperty() patterns
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Current Codebase Tree
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
src/
|
|
118
|
+
├── __tests__/
|
|
119
|
+
│ ├── integration/
|
|
120
|
+
│ │ ├── observer-logging.test.ts # EXISTING - created in S2, verify/enhance coverage
|
|
121
|
+
│ │ ├── agent-workflow.test.ts
|
|
122
|
+
│ │ ├── bidirectional-consistency.test.ts
|
|
123
|
+
│ │ ├── tree-mirroring.test.ts
|
|
124
|
+
│ │ └── workflow-reparenting.test.ts
|
|
125
|
+
│ ├── unit/
|
|
126
|
+
│ │ ├── logger.test.ts # Reference for logger test patterns
|
|
127
|
+
│ │ ├── workflow.test.ts
|
|
128
|
+
│ │ └── observable.test.ts # Reference for mock logger pattern
|
|
129
|
+
│ └── adversarial/
|
|
130
|
+
│ └── observer-propagation.test.ts
|
|
131
|
+
├── core/
|
|
132
|
+
│ ├── workflow.ts # Lines 368-378 (onEvent errors), 390-396 (onStateUpdated errors)
|
|
133
|
+
│ └── logger.ts # Lines 34-45 (onLog error handling)
|
|
134
|
+
├── types/
|
|
135
|
+
│ └── observer.ts # WorkflowObserver interface
|
|
136
|
+
└── utils/
|
|
137
|
+
└── observable.ts # Observable class with logger injection
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Desired Codebase Tree
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
src/
|
|
144
|
+
├── __tests__/
|
|
145
|
+
│ ├── integration/
|
|
146
|
+
│ │ └── observer-logging.test.ts # ENHANCE - add any missing test coverage
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Note**: The test file already exists from S2. This PRP focuses on:
|
|
150
|
+
1. Verifying existing tests cover all scenarios
|
|
151
|
+
2. Adding any missing test coverage (e.g., onTreeChanged errors, console.error negative verification)
|
|
152
|
+
3. Ensuring all tests pass
|
|
153
|
+
|
|
154
|
+
### Known Gotchas of Our Codebase & Library Quirks
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
// CRITICAL: onTreeChanged error handling
|
|
158
|
+
// onTreeChanged is called INSIDE the onEvent try-catch block (workflow.ts:373)
|
|
159
|
+
// So if onTreeChanged throws, it's logged as "Observer onEvent error" with the event type
|
|
160
|
+
// This is by design - onTreeChanged is part of event emission for tree update events
|
|
161
|
+
|
|
162
|
+
// CRITICAL: emitWithoutObserverNotification prevents infinite recursion
|
|
163
|
+
// When observer.onLog() throws, WorkflowLogger uses emitWithoutObserverNotification()
|
|
164
|
+
// to log the error WITHOUT notifying observers again (logger.ts:44)
|
|
165
|
+
|
|
166
|
+
// CRITICAL: Validation errors still use console.error
|
|
167
|
+
// Lines 277, 286 in workflow.ts use console.error for structural validation
|
|
168
|
+
// These are NOT observer execution errors - they should remain as console.error
|
|
169
|
+
|
|
170
|
+
// GOTCHA: Test file already exists from S2
|
|
171
|
+
// src/__tests__/integration/observer-logging.test.ts was created in commit c572b41
|
|
172
|
+
// Verify coverage before adding new tests
|
|
173
|
+
|
|
174
|
+
// PATTERN: Tests verify logs in workflow.node.logs, not console output
|
|
175
|
+
// expect(workflow.node.logs.find(log => log.message === '...')).toBeDefined()
|
|
176
|
+
|
|
177
|
+
// PATTERN: Use vi.spyOn for console.error negative verification
|
|
178
|
+
// const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
179
|
+
// ... run test ...
|
|
180
|
+
// expect(consoleSpy).not.toHaveBeenCalled(); // Verify console.error NOT called
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Implementation Blueprint
|
|
184
|
+
|
|
185
|
+
### Test Architecture
|
|
186
|
+
|
|
187
|
+
The observer error logging tests verify the S2 implementation that replaced `console.error` with `logger.error` for observer execution errors.
|
|
188
|
+
|
|
189
|
+
**Key Test Categories**:
|
|
190
|
+
|
|
191
|
+
1. **onLog Error Tests** (WorkflowObserver.onLog throws)
|
|
192
|
+
- Verify error is logged to `workflow.node.logs`
|
|
193
|
+
- Verify error data contains the error object
|
|
194
|
+
- Verify infinite recursion prevention
|
|
195
|
+
|
|
196
|
+
2. **onEvent Error Tests** (WorkflowObserver.onEvent throws)
|
|
197
|
+
- Verify error is logged with event type context
|
|
198
|
+
- Verify workflow continues execution
|
|
199
|
+
|
|
200
|
+
3. **onStateUpdated Error Tests** (WorkflowObserver.onStateUpdated throws)
|
|
201
|
+
- Verify error is logged with node ID context
|
|
202
|
+
- Verify state snapshot completes
|
|
203
|
+
|
|
204
|
+
4. **onTreeChanged Error Tests** (WorkflowObserver.onTreeChanged throws)
|
|
205
|
+
- Note: onTreeChanged is called inside onEvent try-catch
|
|
206
|
+
- Errors logged as "Observer onEvent error" with treeUpdated event type
|
|
207
|
+
|
|
208
|
+
5. **Error Isolation Tests**
|
|
209
|
+
- Verify workflow doesn't crash when observers throw
|
|
210
|
+
- Verify other observers continue to be notified
|
|
211
|
+
|
|
212
|
+
6. **Multiple Observers Tests**
|
|
213
|
+
- Verify all observers are notified even if some throw
|
|
214
|
+
- Verify error logs for each throwing observer
|
|
215
|
+
|
|
216
|
+
7. **Console.error Negative Verification**
|
|
217
|
+
- Verify `console.error` is NOT called for observer execution errors
|
|
218
|
+
- Verify `console.error` IS still called for validation errors (lines 277, 286)
|
|
219
|
+
|
|
220
|
+
### Implementation Tasks
|
|
221
|
+
|
|
222
|
+
```yaml
|
|
223
|
+
Task 1: REVIEW existing observer-logging.test.ts coverage
|
|
224
|
+
- VERIFY: All observer callbacks have error tests (onLog, onEvent, onStateUpdated, onTreeChanged)
|
|
225
|
+
- VERIFY: Error isolation tests exist
|
|
226
|
+
- VERIFY: Multiple observer tests exist
|
|
227
|
+
- VERIFY: Infinite recursion prevention tests exist
|
|
228
|
+
- IDENTIFY: Any missing test scenarios
|
|
229
|
+
- CHECK: Are there tests verifying console.error is NOT called for observer errors?
|
|
230
|
+
|
|
231
|
+
Task 2: ADD onTreeChanged error test (if missing)
|
|
232
|
+
- IMPLEMENT: Test where observer.onTreeChanged throws during tree update event
|
|
233
|
+
- VERIFY: Error is logged (as "Observer onEvent error" since onTreeChanged is in onEvent try-catch)
|
|
234
|
+
- VERIFY: Event type is 'treeUpdated', 'childAttached', or 'childDetached'
|
|
235
|
+
- FOLLOW: Existing observer error test pattern from observer-logging.test.ts:77-109
|
|
236
|
+
- NAMING: "should log observer onTreeChanged errors (caught as onEvent error)"
|
|
237
|
+
|
|
238
|
+
Task 3: ADD console.error negative verification tests (if missing)
|
|
239
|
+
- IMPLEMENT: Tests using vi.spyOn(console, 'error') to verify it's NOT called
|
|
240
|
+
- VERIFY: For onLog, onEvent, onStateUpdated errors - console.error is NOT invoked
|
|
241
|
+
- VERIFY: For validation errors - console.error IS still invoked (lines 277, 286)
|
|
242
|
+
- FOLLOW: Pattern from observer-logging.test.ts:200-218
|
|
243
|
+
- CLEANUP: Always restore spies with vi.restoreAllMocks() in afterEach or after each test
|
|
244
|
+
|
|
245
|
+
Task 4: ADD hierarchical workflow observer error tests (if missing)
|
|
246
|
+
- IMPLEMENT: Test with parent-child workflow hierarchy
|
|
247
|
+
- VERIFY: Observer on root still receives notifications from child workflows
|
|
248
|
+
- VERIFY: Observer errors in child workflows are logged correctly
|
|
249
|
+
- VERIFY: Parent workflow execution continues when observer errors occur in child
|
|
250
|
+
- FOLLOW: Pattern from observer-propagation.test.ts for hierarchical setup
|
|
251
|
+
|
|
252
|
+
Task 5: VERIFY all tests pass
|
|
253
|
+
- RUN: uv run vitest run src/__tests__/integration/observer-logging.test.ts
|
|
254
|
+
- EXPECTED: All tests pass with no failures
|
|
255
|
+
- DEBUG: If tests fail, check for:
|
|
256
|
+
- Incorrect error message matching
|
|
257
|
+
- Missing log entries
|
|
258
|
+
- Async timing issues (use await for async run() methods)
|
|
259
|
+
- Mock cleanup issues (vi.restoreAllMocks())
|
|
260
|
+
|
|
261
|
+
Task 6: VERIFY no regressions in existing test suite
|
|
262
|
+
- RUN: uv run vitest run src/__tests__/
|
|
263
|
+
- EXPECTED: All existing tests still pass
|
|
264
|
+
- CHECK: No new tests break existing functionality
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Implementation Patterns & Key Details
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
// PATTERN 1: Basic observer error test structure
|
|
271
|
+
describe('Observer Error Logging Integration Tests', () => {
|
|
272
|
+
it('should log observer onEvent errors to workflow.node.logs', () => {
|
|
273
|
+
const onEventError = new Error('Observer onEvent failed');
|
|
274
|
+
|
|
275
|
+
const throwingObserver: WorkflowObserver = {
|
|
276
|
+
onLog: () => {},
|
|
277
|
+
onEvent: () => {
|
|
278
|
+
throw onEventError;
|
|
279
|
+
},
|
|
280
|
+
onStateUpdated: () => {},
|
|
281
|
+
onTreeChanged: () => {},
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
class TestWorkflow extends Workflow {
|
|
285
|
+
async run() {
|
|
286
|
+
this.emitEvent({ type: 'testEvent' });
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const workflow = new TestWorkflow();
|
|
291
|
+
workflow.addObserver(throwingObserver);
|
|
292
|
+
workflow.run();
|
|
293
|
+
|
|
294
|
+
// Verify error log entry exists
|
|
295
|
+
const errorLog = workflow.node.logs.find(
|
|
296
|
+
(log) => log.message === 'Observer onEvent error'
|
|
297
|
+
);
|
|
298
|
+
expect(errorLog).toBeDefined();
|
|
299
|
+
expect(errorLog?.level).toBe('error');
|
|
300
|
+
expect(errorLog?.data).toEqual({
|
|
301
|
+
error: onEventError,
|
|
302
|
+
eventType: 'testEvent',
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// PATTERN 2: Error isolation - workflow continues execution
|
|
308
|
+
it('should not crash workflow when observer onEvent throws', () => {
|
|
309
|
+
const throwingObserver: WorkflowObserver = {
|
|
310
|
+
onLog: () => {},
|
|
311
|
+
onEvent: () => {
|
|
312
|
+
throw new Error('Observer onEvent error');
|
|
313
|
+
},
|
|
314
|
+
onStateUpdated: () => {},
|
|
315
|
+
onTreeChanged: () => {},
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
class TestWorkflow extends Workflow {
|
|
319
|
+
async run() {
|
|
320
|
+
this.emitEvent({ type: 'event1' });
|
|
321
|
+
this.emitEvent({ type: 'event2' });
|
|
322
|
+
this.emitEvent({ type: 'event3' });
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const workflow = new TestWorkflow();
|
|
327
|
+
workflow.addObserver(throwingObserver);
|
|
328
|
+
|
|
329
|
+
// Should complete without throwing
|
|
330
|
+
expect(() => {
|
|
331
|
+
workflow.run();
|
|
332
|
+
}).not.toThrow();
|
|
333
|
+
|
|
334
|
+
// All events should be emitted
|
|
335
|
+
expect(workflow.node.events.length).toBe(3);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// PATTERN 3: Console.error negative verification
|
|
339
|
+
it('should NOT call console.error for observer execution errors', () => {
|
|
340
|
+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
341
|
+
|
|
342
|
+
const throwingObserver: WorkflowObserver = {
|
|
343
|
+
onLog: () => {},
|
|
344
|
+
onEvent: () => {
|
|
345
|
+
throw new Error('Observer error');
|
|
346
|
+
},
|
|
347
|
+
onStateUpdated: () => {},
|
|
348
|
+
onTreeChanged: () => {},
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
class TestWorkflow extends Workflow {
|
|
352
|
+
async run() {
|
|
353
|
+
this.emitEvent({ type: 'testEvent' });
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const workflow = new TestWorkflow();
|
|
358
|
+
workflow.addObserver(throwingObserver);
|
|
359
|
+
workflow.run();
|
|
360
|
+
|
|
361
|
+
// Verify console.error was NOT called for observer error
|
|
362
|
+
expect(consoleErrorSpy).not.toHaveBeenCalled();
|
|
363
|
+
|
|
364
|
+
// Verify error was logged to workflow.node.logs instead
|
|
365
|
+
const errorLog = workflow.node.logs.find(
|
|
366
|
+
(log) => log.message === 'Observer onEvent error'
|
|
367
|
+
);
|
|
368
|
+
expect(errorLog).toBeDefined();
|
|
369
|
+
|
|
370
|
+
consoleErrorSpy.mockRestore();
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// PATTERN 4: Multiple observers with mixed success/failure
|
|
374
|
+
it('should continue notifying other observers after one throws', async () => {
|
|
375
|
+
let observer2Called = false;
|
|
376
|
+
let observer3Called = false;
|
|
377
|
+
|
|
378
|
+
const throwingObserver: WorkflowObserver = {
|
|
379
|
+
onLog: () => {
|
|
380
|
+
throw new Error('Observer 1 failed');
|
|
381
|
+
},
|
|
382
|
+
onEvent: () => {},
|
|
383
|
+
onStateUpdated: () => {},
|
|
384
|
+
onTreeChanged: () => {},
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
const workingObserver2: WorkflowObserver = {
|
|
388
|
+
onLog: () => {
|
|
389
|
+
observer2Called = true;
|
|
390
|
+
},
|
|
391
|
+
onEvent: () => {},
|
|
392
|
+
onStateUpdated: () => {},
|
|
393
|
+
onTreeChanged: () => {},
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
const workingObserver3: WorkflowObserver = {
|
|
397
|
+
onLog: () => {
|
|
398
|
+
observer3Called = true;
|
|
399
|
+
},
|
|
400
|
+
onEvent: () => {},
|
|
401
|
+
onStateUpdated: () => {},
|
|
402
|
+
onTreeChanged: () => {},
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
class TestWorkflow extends Workflow {
|
|
406
|
+
async run() {
|
|
407
|
+
this.logger.info('Test message');
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const workflow = new TestWorkflow();
|
|
412
|
+
workflow.addObserver(throwingObserver);
|
|
413
|
+
workflow.addObserver(workingObserver2);
|
|
414
|
+
workflow.addObserver(workingObserver3);
|
|
415
|
+
|
|
416
|
+
await workflow.run();
|
|
417
|
+
|
|
418
|
+
// Both working observers should have been called
|
|
419
|
+
expect(observer2Called).toBe(true);
|
|
420
|
+
expect(observer3Called).toBe(true);
|
|
421
|
+
|
|
422
|
+
// Should have error log for throwing observer
|
|
423
|
+
const errorLog = workflow.node.logs.find(
|
|
424
|
+
(log) => log.message === 'Observer onLog error'
|
|
425
|
+
);
|
|
426
|
+
expect(errorLog).toBeDefined();
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
// PATTERN 5: Infinite recursion prevention for onLog errors
|
|
430
|
+
it('should avoid infinite recursion when observer onLog throws', async () => {
|
|
431
|
+
let callCount = 0;
|
|
432
|
+
const maxCalls = 10; // Safety limit to prevent actual infinite loop
|
|
433
|
+
|
|
434
|
+
const throwingObserver: WorkflowObserver = {
|
|
435
|
+
onLog: () => {
|
|
436
|
+
callCount++;
|
|
437
|
+
if (callCount < maxCalls) {
|
|
438
|
+
throw new Error('Recursive error');
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
onEvent: () => {},
|
|
442
|
+
onStateUpdated: () => {},
|
|
443
|
+
onTreeChanged: () => {},
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
class TestWorkflow extends Workflow {
|
|
447
|
+
async run() {
|
|
448
|
+
this.logger.info('Test message');
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const workflow = new TestWorkflow();
|
|
453
|
+
workflow.addObserver(throwingObserver);
|
|
454
|
+
await workflow.run();
|
|
455
|
+
|
|
456
|
+
// Should only call onLog once (original) + one error log, then stop
|
|
457
|
+
// The error log should NOT trigger another observer notification
|
|
458
|
+
expect(callCount).toBe(1);
|
|
459
|
+
|
|
460
|
+
// Should have 2 logs: original + error
|
|
461
|
+
expect(workflow.node.logs.length).toBe(2);
|
|
462
|
+
});
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Integration Points
|
|
466
|
+
|
|
467
|
+
```yaml
|
|
468
|
+
NO NEW FILES NEEDED:
|
|
469
|
+
- Test file already exists: src/__tests__/integration/observer-logging.test.ts
|
|
470
|
+
- Implementation code already exists from S2
|
|
471
|
+
|
|
472
|
+
TEST DEPENDENCIES:
|
|
473
|
+
- vitest: Test framework (configured in vitest.config.ts)
|
|
474
|
+
- @vitest/spy: For vi.spyOn() mocking
|
|
475
|
+
|
|
476
|
+
VALIDATION DEPENDS ON:
|
|
477
|
+
- src/core/workflow.ts: Observer error handling implementation
|
|
478
|
+
- src/core/logger.ts: WorkflowLogger with emitWithoutObserverNotification
|
|
479
|
+
- src/types/observer.ts: WorkflowObserver interface
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
## Validation Loop
|
|
483
|
+
|
|
484
|
+
### Level 1: Syntax & Style (Immediate Feedback)
|
|
485
|
+
|
|
486
|
+
```bash
|
|
487
|
+
# Run after any test modifications
|
|
488
|
+
npx tsc --noEmit src/__tests__/integration/observer-logging.test.ts
|
|
489
|
+
|
|
490
|
+
# Expected: No TypeScript errors
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
### Level 2: Unit Tests (Component Validation)
|
|
494
|
+
|
|
495
|
+
```bash
|
|
496
|
+
# Run only the observer logging tests
|
|
497
|
+
uv run vitest run src/__tests__/integration/observer-logging.test.ts
|
|
498
|
+
|
|
499
|
+
# Run with verbose output for detailed results
|
|
500
|
+
uv run vitest run src/__tests__/integration/observer-logging.test.ts --reporter=verbose
|
|
501
|
+
|
|
502
|
+
# Run in watch mode during development
|
|
503
|
+
uv run vitest watch src/__tests__/integration/observer-logging.test.ts
|
|
504
|
+
|
|
505
|
+
# Expected: All tests pass
|
|
506
|
+
# Example output:
|
|
507
|
+
# ✓ src/__tests__/integration/observer-logging.test.ts (N)
|
|
508
|
+
# ✓ WorkflowLogger observer onLog error (N)
|
|
509
|
+
# ✓ should log observer onLog errors to workflow.node.logs
|
|
510
|
+
# ✓ should avoid infinite recursion when observer onLog throws
|
|
511
|
+
# ✓ Workflow observer onEvent error (N)
|
|
512
|
+
# ✓ should log observer onEvent errors via this.logger.error
|
|
513
|
+
# ✓ should include event type in error data
|
|
514
|
+
# ...
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Level 3: Integration Testing (System Validation)
|
|
518
|
+
|
|
519
|
+
```bash
|
|
520
|
+
# Run all integration tests to ensure no regressions
|
|
521
|
+
uv run vitest run src/__tests__/integration/
|
|
522
|
+
|
|
523
|
+
# Run all tests in the project
|
|
524
|
+
uv run vitest run src/__tests__/
|
|
525
|
+
|
|
526
|
+
# Expected: All tests pass, no failures in other test files
|
|
527
|
+
# Verify specifically that logger.test.ts and workflow.test.ts still pass
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### Level 4: Creative & Domain-Specific Validation
|
|
531
|
+
|
|
532
|
+
```bash
|
|
533
|
+
# Run tests with coverage report
|
|
534
|
+
uv run vitest run src/__tests__/integration/observer-logging.test.ts --coverage
|
|
535
|
+
|
|
536
|
+
# Check if observer error handling code is covered
|
|
537
|
+
# Expected: High coverage for:
|
|
538
|
+
# - src/core/workflow.ts:368-378 (onEvent error handling)
|
|
539
|
+
# - src/core/workflow.ts:390-396 (onStateUpdated error handling)
|
|
540
|
+
# - src/core/logger.ts:34-45 (onLog error handling)
|
|
541
|
+
|
|
542
|
+
# Adversarial testing - run stress tests
|
|
543
|
+
uv run vitest run src/__tests__/adversarial/
|
|
544
|
+
|
|
545
|
+
# Expected: No adversarial tests broken by observer error handling changes
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
## Final Validation Checklist
|
|
549
|
+
|
|
550
|
+
### Technical Validation
|
|
551
|
+
|
|
552
|
+
- [ ] All 4 validation levels completed successfully
|
|
553
|
+
- [ ] All observer-logging tests pass: `uv run vitest run src/__tests__/integration/observer-logging.test.ts`
|
|
554
|
+
- [ ] No TypeScript errors: `npx tsc --noEmit src/__tests__/integration/observer-logging.test.ts`
|
|
555
|
+
- [ ] No regressions: `uv run vitest run src/__tests__/` passes completely
|
|
556
|
+
- [ ] Console.error NOT called for observer execution errors (verified via vi.spyOn tests)
|
|
557
|
+
- [ ] Console.error IS still called for validation errors (lines 277, 286)
|
|
558
|
+
|
|
559
|
+
### Feature Validation
|
|
560
|
+
|
|
561
|
+
- [ ] All success criteria from "What" section met
|
|
562
|
+
- [ ] onLog error logging tests pass with infinite recursion prevention
|
|
563
|
+
- [ ] onEvent error logging tests pass with event type context
|
|
564
|
+
- [ ] onStateUpdated error logging tests pass with node ID context
|
|
565
|
+
- [ ] onTreeChanged error handling tested (via onEvent since it's in same try-catch)
|
|
566
|
+
- [ ] Error isolation verified - workflow continues after observer errors
|
|
567
|
+
- [ ] Multiple observers tested - others notified after one throws
|
|
568
|
+
- [ ] Structured error context verified in log entries
|
|
569
|
+
|
|
570
|
+
### Code Quality Validation
|
|
571
|
+
|
|
572
|
+
- [ ] Tests follow existing patterns from observer-logging.test.ts
|
|
573
|
+
- [ ] Descriptive test names using "should" pattern
|
|
574
|
+
- [ ] Proper mock cleanup with vi.restoreAllMocks()
|
|
575
|
+
- [ ] Tests are isolated (no shared state between tests)
|
|
576
|
+
- [ ] Test coverage is comprehensive for all observer callbacks
|
|
577
|
+
|
|
578
|
+
### Documentation & Deployment
|
|
579
|
+
|
|
580
|
+
- [ ] Test file is self-documenting with clear describe/it blocks
|
|
581
|
+
- [ ] Complex test scenarios have explanatory comments
|
|
582
|
+
- [ ] Test file location matches convention (src/__tests__/integration/)
|
|
583
|
+
|
|
584
|
+
---
|
|
585
|
+
|
|
586
|
+
## Anti-Patterns to Avoid
|
|
587
|
+
|
|
588
|
+
- ❌ Don't create a new test file - use existing `observer-logging.test.ts`
|
|
589
|
+
- ❌ Don't test console.error output - test `workflow.node.logs` content instead
|
|
590
|
+
- ❌ Don't forget to restore vi.spyOn mocks - always use vi.restoreAllMocks()
|
|
591
|
+
- ❌ Don't share state between tests - create fresh observers for each test
|
|
592
|
+
- ❌ Don't use setTimeout for timing - use proper async/await
|
|
593
|
+
- ❌ Don't test implementation details - test behavior (errors logged, workflow continues)
|
|
594
|
+
- ❌ Don't remove validation error console.error tests (lines 277, 286) - these are correct
|
|
595
|
+
- ❌ Don't add tests that are duplicates of existing S2 tests - verify coverage first
|
|
596
|
+
|
|
597
|
+
## Context Completeness Validation
|
|
598
|
+
|
|
599
|
+
This PRP passes the "No Prior Knowledge" test:
|
|
600
|
+
|
|
601
|
+
✅ File locations specified with line numbers
|
|
602
|
+
✅ Existing test file identified and analyzed
|
|
603
|
+
✅ Test patterns provided with code examples
|
|
604
|
+
✅ External documentation URLs included with anchors
|
|
605
|
+
✅ Known gotchas documented (onTreeChanged in onEvent try-catch, emitWithoutObserverNotification)
|
|
606
|
+
✅ Validation commands are project-specific and verified
|
|
607
|
+
✅ Implementation tasks are dependency-ordered and specific
|
|
608
|
+
✅ Anti-patterns section prevents common mistakes
|
|
609
|
+
|
|
610
|
+
**Confidence Score for One-Pass Implementation Success: 9/10**
|
|
611
|
+
|
|
612
|
+
The existing test file from S2 provides an excellent foundation. This PRP provides clear guidance on verifying and enhancing test coverage with specific patterns to follow.
|