Files
aditya d17895dae2 feat(events): add EventBus protocol and ReactiveEventBus implementation
- Add EventType StrEnum with 38 typed domain event identifiers across 8
  domains (plan lifecycle, decision, actor, tool, resource, sandbox,
  validation, session, budget)
- Add frozen DomainEvent Pydantic model with event_type, auto-UTC
  timestamp, auto-ULID correlation_id, plan_id, root_plan_id,
  session_id, actor_name, project_name, and details fields
- Add @runtime_checkable EventBus Protocol with emit() and subscribe()
- Add ReactiveEventBus backed by RxPY Subject for in-process reactive
  streaming with synchronous handler dispatch and raw Observable stream
- Add LoggingEventBus using structlog for audit-trail-only environments
- Wire DecisionService to emit DECISION_CREATED on record_decision()
- Wire PlanLifecycleService to emit PLAN_CREATED and PLAN_PHASE_CHANGED
  on use_action() and execute_plan() respectively
- Register ReactiveEventBus as Singleton in DI container and inject into
  DecisionService and PlanLifecycleService providers
- Add Behave BDD unit tests: 27 scenarios, 75 steps, 100% branch coverage
- Add Robot Framework integration tests: 9 smoke cases
- Add ASV performance benchmarks: 5 suites covering emit throughput and
  subscriber fan-out
- Add reference documentation at docs/reference/event_bus.md

ISSUES CLOSED: #473
2026-03-02 11:54:53 +00:00

92 lines
3.9 KiB
Plaintext

*** Settings ***
Documentation Smoke tests for EventBus infrastructure (EventType, DomainEvent,
... ReactiveEventBus, LoggingEventBus, service emission, DI container)
Resource ${CURDIR}/common.resource
Suite Setup Setup Test Environment
Suite Teardown Cleanup Test Environment
*** Variables ***
${HELPER} ${CURDIR}/helper_event_bus.py
*** Test Cases ***
EventType Values Are Present
[Documentation] Verify all required EventType string values exist
${result}= Run Process ${PYTHON} ${HELPER} event_type_values
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} event-type-values-ok
DomainEvent Creation With Defaults
[Documentation] Verify DomainEvent constructs and applies default fields
${result}= Run Process ${PYTHON} ${HELPER} domain_event_creation
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} domain-event-creation-ok
Protocol Conformance
[Documentation] Verify both bus implementations satisfy EventBus protocol
${result}= Run Process ${PYTHON} ${HELPER} protocol_conformance
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} protocol-conformance-ok
ReactiveEventBus Emit And Subscribe
[Documentation] Verify ReactiveEventBus dispatches events to handlers
${result}= Run Process ${PYTHON} ${HELPER} reactive_emit_subscribe
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} reactive-emit-subscribe-ok
LoggingEventBus Emit And Subscribe
[Documentation] Verify LoggingEventBus dispatches events to handlers
${result}= Run Process ${PYTHON} ${HELPER} logging_emit_subscribe
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} logging-emit-subscribe-ok
ReactiveEventBus Type Filtering
[Documentation] Verify ReactiveEventBus only dispatches to matching event type
${result}= Run Process ${PYTHON} ${HELPER} reactive_type_filtering
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} reactive-type-filtering-ok
DecisionService Emits DECISION_CREATED
[Documentation] Verify DecisionService emits event via injected bus
${result}= Run Process ${PYTHON} ${HELPER} decision_service_emits_event
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} decision-service-emits-event-ok
PlanLifecycleService Emits PLAN_CREATED
[Documentation] Verify PlanLifecycleService emits event via injected bus
${result}= Run Process ${PYTHON} ${HELPER} plan_lifecycle_emits_event
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} plan-lifecycle-emits-event-ok
Container EventBus Is Singleton
[Documentation] Verify DI container provides same ReactiveEventBus instance
${result}= Run Process ${PYTHON} ${HELPER} container_event_bus_singleton
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} container-event-bus-singleton-ok