- conforms_to::[[Conviction Form Contract]]
- in_practice_domain::[[eOS Continuum]]
- authored_by::[[Christopher Allen]]
- has_lifecycle::[[Seed Stage]]↗
- has_curation::[[Working Draft]]↗
Event Notification Is Atomic With State Change, Not Polled or Queued
The eOS runtime platform fires event notifications synchronously inside the atomic operation that caused the state change. Registered listeners observe the same atomic envelope as the change itself; the event and the post-event state are inseparable atomic outcomes. Agents react to state without polling, and without race conditions, because the runtime guarantees there is no observable moment in which the state has changed but the event has not fired, or in which the event has fired but the state has not changed.
Why It Is Held
Event-notification patterns built outside the runtime fragment. Each team picks a polling interval, a queue technology, a delivery-semantic (at-least-once, at-most-once, exactly-once) and reasons through edge cases (what happens when the listener is mid-process when the queue redelivers). Each implementation has bugs the team rebuilds when discovered, and each requires reasoning about race conditions that the runtime primitive removes by construction. Treating event notification as atomic with state change collapses the entire reasoning surface: there are no edge cases because there is no time gap between state change and event observation -- both are committed in the same atomic envelope or both roll back together.
The "asynchronous" framing names the agent-side experience, not the runtime-side mechanism. From the agent's perspective, the agent did not have to poll, did not have to write queue-consumer code, did not have to manage a separate dispatch loop -- it registered a listener, and the listener fired when state changed. From the runtime's perspective, the listener fired synchronously inside the atomic operation that caused the change. The asymmetry is what makes the primitive load-bearing: agents get the cleanliness of asynchronous reaction without the race-condition surface that cross-operation asynchrony usually produces.
The platform-as-event-coordinator stance composes tightly with the atomic primitive ([[Agent Operations Commit Wholly or Roll Back Wholly]]). Event firing is part of the atomic envelope: if the operation rolls back, the event "did not fire" in the same sense that the state change "did not occur" -- both are absent from the post-rollback state, both are absent from any listener's observation, and the runtime carries the bookkeeping that makes this guarantee invisible to agent code. Without atomicity, event notification would have to coordinate with rollback explicitly (was the event delivered? does the listener need a compensating event?), recreating the per-team reasoning surface the primitive removes.
The platform-as-event-coordinator stance also composes with coherent multi-agent semantics ([[Multiple Agents See Coherent State Without User-Land Coordination]]). Events are how agents react to other agents' state changes; in a coherent-state runtime, an agent registering a listener sees the same atomic events that every other agent sees, in the same order, without any of them having to coordinate on a shared event log. The primitives reinforce each other at the multi-agent boundary: coherent state needs an in-runtime event mechanism; events need coherent state to make listener registrations meaningful across agents.
The eOS-kernellib foundation provides asynchronous building blocks at the runtime layer: delayed callbacks, async I/O for external triggers, and datagram and connection-oriented ports for cross-process events. The kernel layer's connection daemon mediates connection-event creation. What the foundation does not yet coordinate as a single event-dispatch loop is the agent-facing surface -- an event-dispatch wrapper (queue, coroutines, or continuations) is needed to expose the platform's primitive cleanly to agent code.
The Conviction is held because the no-race-condition agent-coding experience is what platform adoption purchases for the multi-agent reactive scenario. When listener-fires-with-state-change is the runtime's promise, agent code reasons locally about state transitions rather than globally about event ordering. Trading the primitive for an external event broker (Kafka, RabbitMQ, application-layer queue) would reintroduce exactly the cross-system delivery semantics and race-condition reasoning the primitive removes, while losing atomic-rollback coordination across the system boundary.
What It Asks
Honoring this Conviction asks the project to keep event notification inside the atomic envelope, not to delegate it to external brokers or to polling.
- Tests and demonstrations register listeners directly with runtime objects, not with external pub-sub systems. The architecture under test operates on objects whose state changes can be observed by registered listeners, with listener registration as the agent-facing API rather than poll-and-compare.
- The event-dispatch surface closes the foundation's gap by adding a wrapper that preserves the atomic-envelope guarantee. A wrapper that queues events for cross-operation delivery (delayed-callback semantics) is operating outside the platform's primitive for those events; the wrapper must distinguish atomic-synchronous notifications from genuinely-cross-operation deferred operations and surface the boundary to consumers.
- Decisions introducing external event brokers must surface the cost. A Decision adding "for cross-instance event distribution, route events through Kafka" or "for legacy integration, publish events to RabbitMQ" reintroduces the cross-system delivery semantics and race-condition surface the primitive removes. The platform is single-coherence-domain by design, so cross-instance event distribution is outside the platform's primitive entirely.
- Communication distinguishes atomic-synchronous-within-operation from queued-asynchronous-across-operations. When the project's event-notification claim is communicated externally, the distinction between in-atomic-envelope listener-fire and queued cross-operation delivery is the load-bearing detail. The two are sometimes conflated in agent-infrastructure copy that uses "event-driven" loosely.
- Workstream scoping checks the event-coordination layer for new agent capabilities. Workstreams adding capabilities that need cross-instance event coordination (multi-machine coordination, cross-organization event flows) need to acknowledge they are operating outside the platform's primitive for those events; the platform's primitive operates within a single coherence domain.
Drift Recognition
The Conviction has weakened when the project's outputs treat event notification as a cross-operation pattern requiring user-code coordination, rather than as an atomic-envelope guarantee.
- Agent code that polls for state changes instead of registering listeners. When agent code accumulates "check this state every N seconds" or "compare to last-known-state" patterns, the platform's listener-fires-with-state-change primitive is being worked around. The polling itself is the drift evidence; in a held-Conviction world, polling is what the listener primitive replaces.
- Event queues introduced for at-least-once or at-most-once delivery semantics. A Decision adding a queue layer between state change and listener observation inverts the Conviction's stance. Once a queue intermediates, the atomic envelope no longer covers the event delivery, and the cross-operation race conditions the primitive removes return.
- External event brokers (Kafka, RabbitMQ, NATS) added for in-runtime event flow. When the operational pattern for in-runtime events routes them through an external broker, the platform has been demoted from "event coordinator" to "event publisher to a separate system." The demotion may be defensible for cross-instance integration scenarios; it is drift when applied to in-runtime events the platform's primitive already handles.
- "Eventually-consistent listener observation" framings. The Conviction's stance is that listener observation is atomic with state change -- there is no consistency window. Documentation that describes listener observation as eventually-consistent has weakened the Conviction; eventual consistency is what the platform's primitive replaces.
- Cumulative drift across multiple sessions. If several consecutive rounds of work add features that quietly lean on polling, queuing, or external broker patterns for in-runtime events without surfacing the platform-fit cost, the project has drifted from holding the Conviction.
Relations
-
conforms_to::[[Conviction Form Contract]]
- Exercises the Contract's Stance plus Why It Is Held plus What It Asks plus Drift Recognition body shape. The filename uses the held-stance comma form ("X is Y, Not Z").
-
grounded_in::[[Agent Runtimes Require Native Primitives, Not External Glue]]
- The asynchronous-events primitive is one instance of the broader stance that what is normally a pattern (polling loops, external event brokers, application-layer dispatch) becomes a primitive in the runtime that every line of agent code can rely on; external event-broker patterns (Kafka, RabbitMQ, EventBridge, webhook plumbing) cannot deliver platform-level synchronous event-fire inside the same atomic operation. Currently a ghost link; the diagnostic Conviction has not yet migrated.
-
grounded_in::[[Runtime State Is Persistent by Default, Not by Application Discipline]]
- Asynchronous events matter because they fire atomically with persistent state changes: a listener observes the same durable state transition every other reader of the persistent image will observe, not a transient in-memory signal that a restart could silently drop.
-
composes_with::[[Agent Operations Commit Wholly or Roll Back Wholly]]
- Asynchronous events and atomicity reinforce each other tightly: event firing is part of the atomic envelope; if the operation rolls back, the event "did not fire" in the same sense that the state change "did not occur". Without atomicity, event notification would have to coordinate with rollback explicitly (was the event delivered? does the listener need a compensating event?). With atomicity, event-fire and state-change are the same atomic outcome; either both are present or both are absent.
-
composes_with::[[Multiple Agents See Coherent State Without User-Land Coordination]]
- Asynchronous events and coherent multi-agent semantics reinforce each other at the multi-agent boundary: events are how agents react to other agents' state changes; coherent state is what makes listener registrations meaningful across agents. A multi-agent runtime without atomic-envelope events would force agents to coordinate on a shared event log; a coherent-state runtime without event notification would force agents to poll. Both stances together make the multi-agent reactive scenario coherent. Currently a ghost link; the multi-agent-coherence Conviction has not yet migrated.