- conforms_to::[[Observation Form Contract]]
- has_epistemic_status::[[Empirical Observation]]
- in_practice_domain::[[eOS Continuum]]
- authored_by::[[Christopher Allen]]
- has_lifecycle::[[Seed Stage]]↗
- has_curation::[[Working Draft]]↗
A Cross-User Notification Fires Within the Posting Write's Atomic Envelope and Rolls Back With It
Claim
In the eOS-Harness MVA running against DGD 1.7.9 plus the eOSContinuum/eOS-kernellib feature/cohesive-lift branch (Vault + Schema + XML + Index + Merry + the property-change dispatcher), posting a chat message that mentions a user fires a registered observer synchronously, inside the same set_property that records the message, and that observer's cross-user write shares the posting write's atomic fate. The dispatch shape: a chat-room carries an append-to-history main observer and a mention-notify post observer (both registered via MERRY->register_observer under merry:on:chat-room.message:<timing>). The chat daemon's post_message resolves the @name mentions against the room roster and writes one chat-room.message arrival signal via set_property; the dispatcher fires the main append, then the post mention-notify observer, both within that write. The mention-notify observer runs Set($new["mentions"][0], "chat-user.mention-tracker", Get(...) + ({ $this })), so the mentioned user's tracker names the room the instant post_message returns (sentinel EVENT-ATOMIC OK). When the same post is wrapped in a DGD atomic function that then throws, the rollback unwinds every write the task made -- the message-log append and the observer's cross-user Set alike -- so neither the message nor the notification survives (sentinel EVENT-ROLLBACK OK). The sender's post_message contains no notification logic; the "asynchronous" character is the agent-side experience (a registered listener, no polling), while the mechanism is synchronous-within-the-atomic-envelope.
Grounds
This is an Empirical Observation. The grounds are a captured three-boot smoke run 2026-05-30 against the live MVA demonstration instance with examples/chat-app/ overlaid at the isolated runtime staging tree's src/usr/Chat/.
Setup (verifiable from repo state):
- Driver: DGD 1.7.9 built from
dworkin/dgd; binary symlinked at the isolated runtime staging tree'sbin/dgd. - Kernel layer:
eOSContinuum/eOS-kernellibonfeature/cohesive-liftat HEADd333bd4(the synchronous-atomic chat-app correction; a runtime-layer continuation fix at4aec423). - Application layer:
examples/chat-app/, deployed into the isolated runtime staging tree with the Chat domain overlay. - Runtime config: the instance config; the isolated runtime staging tree layout; the three-boot regression harness, which counts
OKsentinels (expected 11).
Load-bearing source (phases 5 and 7 of examples/chat-app/sys/test.c):
/* phase 5: synchronous notification */
MERRY_DAEMON->register_observer(room_p5, "chat-room.message", "post", SRC_NOTIFY);
CHAT_DAEMON->post_message(alice, room_p5, "@dave hi");
/* dave->query_mention_tracker() == ({ room_p5 }) already */
/* phase 7: the same post inside an atomic envelope that throws */
static atomic void atomic_post_then_fail(object sender, object room, string content)
{
CHAT_DAEMON->post_message(sender, room, content);
error("EVENT-ROLLBACK deliberate failure");
}
/* after the caught throw: room has no message, eve has no notification */
SRC_NOTIFY is the post observer source Set($new["mentions"][0], "chat-user.mention-tracker", Get($new["mentions"][0], "chat-user.mention-tracker") + ({ $this })); return TRUE; -- pure Merry, no $delay. post_message writes chat-room.message; the dispatcher's dispatch_set fires the registered observers synchronously around the raw write.
Smoke transcript (the load-bearing portion of the result log after boot 1):
ChatApp:test: EVENT-ATOMIC OK
ChatApp:test: NO-REACT OK
ChatApp:test: EVENT-ROLLBACK OK
EVENT-ATOMIC OK writes only when dave's mention-tracker equals ({ room_p5 }) immediately after post_message returns (the notification landed synchronously). EVENT-ROLLBACK OK writes only when the atomic post threw AND the room's message log is empty AND eve's mention-tracker is empty (both writes rolled back). Both are inside catch{}; a throw or a surviving write logs a distinct FAIL.
What the evidence establishes:
- A registered observer fires synchronously inside the
set_propertythat triggered it: the cross-user notification is observable the instant the triggering call returns, with no later tick and no poll. - The notification shares the triggering write's atomic envelope: when the post's atomic operation rolls back, the notification is absent in the same way the message is absent. There is no observable state in which the message rolled back but the notification fired.
- The sender is decoupled from the handler at the code level:
post_messagenames no listener and contains no notification logic; the reaction happens solely because an observer is registered.
What the evidence does not establish:
- Deferred operations. The notification here is synchronous by design; a genuinely deferred operation (a
$delaycontinuation running on a later tick, outside the atomic envelope) is a distinct capability, demonstrated separately by the example'sDEFERRED-OPphase and kept distinct precisely so the two are not conflated. - Cross-instance event distribution. The demonstration is single-coherence-domain; events crossing a process or machine boundary are outside the platform's primitive and not exercised.
- Listener registration over an untrusted transport. Observers are registered by the boot-time driver via the capability-gated
register_observer(domain-match accept path); an end-to-end "an external party registered this listener" flow is not exercised.
What Would Revise It
- A demonstration that listener observation is eventually-consistent rather than synchronous would contradict the claim; the current evidence shows the tracker populated before the triggering call returns, with no consistency window.
- A rollback case where the notification survived would falsify the atomic-envelope claim; the current evidence shows both writes absent after the atomic throw.
- A DGD or eOS-kernellib change to
atomic{}rollback semantics or the dispatcher's synchronous fan-out would invalidate the snapshot; the claim rests on DGD 1.7.9 plusfeature/cohesive-liftHEADd333bd4.
Sources
examples/chat-app/sys/test.c(ineOS-kernellib feature/cohesive-lift) -- phases 5 (EVENT-ATOMIC) and 7 (EVENT-ROLLBACK), andatomic_post_then_fail.examples/chat-app/sys/chat.c--post_messagewrites thechat-room.messagearrival signal;scan_mentionsresolves@nameto member objects.src/usr/Merry/sys/merry.c--dispatch_setfires pre/main/post observers synchronously around the raw write;register_observer's capability gate.src/usr/Merry/lib/merrynode.c-- theSetmerryfun (Set(object o, ...)forwards too->set_property, allowing the cross-user write).docs/chat-applications.md(ineOS-kernellib feature/cohesive-lift) -- the "Async events" walkthrough; phases 5 and 7.docs/dispatcher.md-- the dispatcher contract; the synchronous fan-out and the atomic-envelope cooperation withset_property.- The isolated runtime staging tree's
src/usr/Chat/data/test-result.log-- the sentinel file; carriesEVENT-ATOMIC OKandEVENT-ROLLBACK OKafter a clean boot. - The three-boot regression harness and the instance config.
Relations
-
conforms_to::[[Observation Form Contract]]
- Carries
has_epistemic_status::[[Empirical Observation]], names the measurement (one three-boot smoke run; two synchronous assertions in phases 5 and 7), states the limits (synchronous only -- deferred operations are a separate capability; single-coherence-domain; driver-registered listeners), and lists concrete revision conditions.
- Carries
-
informs_downstream::[[Event Notification Is Atomic With State Change, Not Polled or Queued]]
- The Conviction holds that event notification fires synchronously inside the atomic operation that caused the change, and that the "asynchronous" framing names the agent-side experience, not a queued or deferred mechanism. This Observation is the positive evidence: the notification lands synchronously (EVENT-ATOMIC) and rolls back with the state change (EVENT-ROLLBACK). The rollback case is the sharpest evidence -- it shows event-fire and state-change are the same atomic outcome.
-
contrasts_with::[[A Property Change Fires No Reaction Where No Observer Is Registered]]
- The negative-case peer. This case shows a registered observer firing atomically with the write; the negative shows that with no observer registered, the same write fires no reaction. The two together bound the mechanism: reactions are exactly the registered observers, fired synchronously, and nothing else.