Files
cleveragents-core/robot/event_system_taxonomy_integration.robot
T
CoreRasurae 00881a3e5f
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 3m26s
CI / build (pull_request) Successful in 14s
CI / typecheck (pull_request) Successful in 4m2s
CI / quality (pull_request) Successful in 4m2s
CI / security (pull_request) Successful in 4m23s
CI / integration_tests (pull_request) Successful in 9m35s
CI / unit_tests (pull_request) Successful in 9m39s
CI / docker (pull_request) Successful in 2m15s
CI / e2e_tests (pull_request) Successful in 12m32s
CI / coverage (pull_request) Successful in 11m41s
CI / status-check (pull_request) Successful in 1s
CI / build (push) Successful in 23s
CI / lint (push) Successful in 3m17s
CI / typecheck (push) Successful in 4m11s
CI / quality (push) Successful in 4m11s
CI / security (push) Successful in 4m28s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 9m13s
CI / unit_tests (push) Successful in 9m26s
CI / e2e_tests (push) Successful in 10m20s
CI / docker (push) Successful in 1m16s
CI / coverage (push) Successful in 12m2s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Successful in 33m17s
CI / benchmark-regression (pull_request) Successful in 57m23s
feat(observability): implement Event System Domain Event Taxonomy (full EventType enum + DomainEvent model)
Verified and completed the Event System Domain Event Taxonomy implementation.

Gap analysis:
- EventType enum (38 types across 12 domains): ALREADY EXISTED, verified complete
- DomainEvent Pydantic model (all 9 fields): ALREADY EXISTED, verified complete
- EventBus Protocol (emit + subscribe): ALREADY EXISTED, verified complete
- ReactiveEventBus (RxPY Subject, stream property): ALREADY EXISTED, verified
- LoggingEventBus (structlog-based): ALREADY EXISTED, verified complete

Added:
- In-memory audit_log on ReactiveEventBus (list[DomainEvent] with defensive copy)
- Emit ordering aligned with specification: RxPY stream push, then audit append,
  then handler dispatch (§Event System)
- Clarified audit_log docstring: volatile in-memory log, not durable SQLite
  persistence (durable persistence wired separately via audit service layer)
- Behave feature: features/observability/event_system_taxonomy.feature (36 scenarios)
- Step definitions: features/steps/event_system_taxonomy_steps.py
- Robot integration test: robot/event_system_taxonomy_integration.robot (13 test cases)
- Robot helper: robot/helper_event_system_taxonomy.py (13 subcommands)
- ASV benchmark: benchmarks/bench_event_bus.py (5 benchmark suites)
- vulture_whitelist.py: added audit_log property

Code review fixes applied:
- Reordered emit() to match spec: on_next → audit_log → handlers (was: audit → on_next → handlers)
- Clarified audit_log docstring to distinguish volatile in-memory log from spec SQLite table
- Fixed benchmark TaxonomyAuditLogSuite: parameterized setup instead of inline construction
- Added teardown to TaxonomyLoggingEmitSuite to restore logging.disable(NOTSET)
- Clear _received list between benchmark iterations to reduce noise
- Catch specific pydantic.ValidationError in frozen model mutation tests
- Consolidated duplicate singular/plural step definitions
- Tightened EventType count threshold from >=30 to >=38

Quality gates:
- lint: PASSED
- typecheck: PASSED (0 errors)
- unit_tests: 36/36 new scenarios PASSED (pre-existing 12 flaky failures unchanged)
- integration_tests: 1483/1483 PASSED
- security_scan: PASSED
- dead_code: PASSED

ISSUES CLOSED: #587
2026-03-26 11:52:52 +00:00

193 lines
8.5 KiB
Plaintext

*** Settings ***
Documentation Integration tests for Event System Domain Event Taxonomy
... Validates EventType completeness, DomainEvent model fields,
... ReactiveEventBus emit/subscribe/stream/audit_log, and
... LoggingEventBus conformance.
Resource ${CURDIR}/common.resource
Suite Setup Setup Test Environment
Suite Teardown Cleanup Test Environment
*** Variables ***
${HELPER} ${CURDIR}/helper_event_system_taxonomy.py
*** Test Cases ***
EventType Enum Has At Least 43 Members
[Documentation] Verify the EventType enum defines at least 43 event types
${result}= Run Process ${PYTHON} ${HELPER} event_type_count
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} event-type-count-ok
EventType Covers All Required Domains
[Documentation] Verify EventType has values for all required domains
${result}= Run Process ${PYTHON} ${HELPER} event_type_domains
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} event-type-domains-ok
EventType Values Follow Dot Convention
[Documentation] Every value matches <domain>.<action>
${result}= Run Process ${PYTHON} ${HELPER} event_type_dot_convention
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} event-type-dot-convention-ok
DomainEvent Has All Required Fields
[Documentation] Verify DomainEvent includes all spec-required fields
${result}= Run Process ${PYTHON} ${HELPER} domain_event_fields
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} domain-event-fields-ok
DomainEvent JSON Round Trip
[Documentation] Serialize and deserialize a fully populated DomainEvent
${result}= Run Process ${PYTHON} ${HELPER} domain_event_json_roundtrip
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} domain-event-json-roundtrip-ok
DomainEvent Is Immutable
[Documentation] Frozen model rejects field mutation
${result}= Run Process ${PYTHON} ${HELPER} domain_event_immutable
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} domain-event-immutable-ok
ReactiveEventBus Emit Subscribe Audit
[Documentation] Emit dispatches to handlers and persists to audit_log
${result}= Run Process ${PYTHON} ${HELPER} reactive_emit_subscribe_audit
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} reactive-emit-subscribe-audit-ok
ReactiveEventBus Continues Dispatching After Handler Error
[Documentation] A failing handler does not block subsequent handlers
${result}= Run Process ${PYTHON} ${HELPER} reactive_handler_exception_isolation
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} reactive-handler-exception-isolation-ok
ReactiveEventBus Continues After Stream Observer Error
[Documentation] A failing stream observer does not block handlers or audit
${result}= Run Process ${PYTHON} ${HELPER} reactive_stream_exception_isolation
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} reactive-stream-exception-isolation-ok
ReactiveEventBus Stream Observable
[Documentation] stream property exposes rx.Observable that receives events
${result}= Run Process ${PYTHON} ${HELPER} reactive_stream_observable
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} reactive-stream-observable-ok
ReactiveEventBus Stream Is Read Only
[Documentation] stream should not expose Subject mutation methods
${result}= Run Process ${PYTHON} ${HELPER} reactive_stream_read_only
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} reactive-stream-read-only-ok
ReactiveEventBus Audit Log Order
[Documentation] audit_log preserves emission order
${result}= Run Process ${PYTHON} ${HELPER} audit_log_order
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} audit-log-order-ok
ReactiveEventBus Audit Log Defensive Copy
[Documentation] audit_log returns a copy — external mutation is safe
${result}= Run Process ${PYTHON} ${HELPER} audit_log_defensive_copy
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} audit-log-defensive-copy-ok
ReactiveEventBus Audit Log Retention Cap
[Documentation] configured cap keeps only newest events and supports clearing
${result}= Run Process ${PYTHON} ${HELPER} audit_log_retention_cap
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} audit-log-retention-cap-ok
ReactiveEventBus Rejects Invalid Audit Log Retention Cap
[Documentation] max_audit_log_size must be positive when provided
${result}= Run Process ${PYTHON} ${HELPER} audit_log_invalid_retention_cap
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} audit-log-invalid-retention-cap-ok
Log Correlation Via Shared Correlation ID
[Documentation] Events sharing a correlation_id are traceable in audit_log
${result}= Run Process ${PYTHON} ${HELPER} log_correlation
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} log-correlation-ok
Protocol Conformance For Both Bus Implementations
[Documentation] Both ReactiveEventBus and LoggingEventBus satisfy EventBus
${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
LoggingEventBus Emit Subscribe
[Documentation] LoggingEventBus dispatches to subscribed 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
LoggingEventBus Continues Dispatching After Handler Error
[Documentation] LoggingEventBus isolates handler exceptions and continues
${result}= Run Process ${PYTHON} ${HELPER} logging_handler_exception_isolation
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} logging-handler-exception-isolation-ok
ReactiveEventBus Type Validation
[Documentation] Emit/subscribe reject invalid argument types
${result}= Run Process ${PYTHON} ${HELPER} type_validation
... cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} type-validation-ok