You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
arch(events): workflow_completed and workflow_cancelled are published on two transports under one name #17676
Found while building the per-transport contract guard for #17643. The two producers' vocabularies are otherwise disjoint — these two are the entire overlap:
bus only workflow_approval workflow_approval_required workflow_step_started
workflow_step_completed workflow_failed
both workflow_completed workflow_cancelled
socket automation_control_refused start_workflow step_confirmation_required
only step_failed step_rejected_by_judge workflow_paused
workflow_plan_presented workflow_resumed
Why it matters
A name shared across transports cannot be reasoned about from the consumer side. #17643's original acceptance criterion asked for a guard that the frontend's event names are a subset of "the backend's published set" — for these two names a union of the producers cannot say which one a given consumer is reading, and for the other thirteen it certifies names that can never reach that consumer. The overlap is why the union framing is wrong rather than merely imprecise.
It is also duplicate publishing: a completing workflow emits a completion twice, by two mechanisms, with different payloads (the bus carries total_steps and execution_time; the socket carries the executor's own shape). Any consumer reading both would double-count.
Current state
Pinned, not fixed. repo_tests/workflow_event_contract_17643_test.py::test_the_shared_names_are_exactly_the_two_we_know_about asserts the overlap is exactly these two, so a third shared name fails and forces a decision rather than quietly widening an overlap nobody chose.
Acceptance criteria
A recorded decision on whether a workflow lifecycle event has one transport or two — consolidate, or document why both exist, in EVENT_STATE_DOCTRINE.md, which currently says nothing about either path
If consolidated: one producer per lifecycle event, with the consumers moved to it and the redundant publish removed
If kept: the two names are distinguished so one string does not mean two things on two sockets
The overlap pin in workflow_event_contract_17643_test.py updated to match the decision, not deleted
Activity
fix(frontend): the workflow dashboard filtered on two events nobody p…