Open Mission Entity events are public Entity boundary facts declared by the owning Entity contract. They are not terminal byte streams, socket implementation details, registry-private callback names, or UI-local refresh hints.

Decision

Every public Entity event family is declared in <Entity>Contract.ts under events, with its payload schema owned by <Entity>Schema.ts or by the schema module of the first-class Entity whose payload is being carried. The contract declaration is the authoritative event list for the Entity boundary.

An Entity event published outside the Entity process must be carried as EntityEventEnvelopeSchema:

  • entityId addresses the owning Entity instance by canonical table:uniqueId id.
  • channel is derived as entityId.eventName, such as terminal:<id>.data.changed.
  • eventName is the contract event name, such as data.changed or recordingEntry.appended.
  • kind is the application-facing event kind and defaults to <entityNameLowerFirst>.<eventName>, such as terminal.data.changed.
  • payload must parse through the payload schema declared by the owning Entity contract.

Open Mission surfaces must route live Entity notifications by kind. eventName remains part of the canonical envelope for channel derivation and contract identity, but browser-facing consumers must not treat it as the primary application discriminator when kind is available.

The generic Entity layer may create contract-validated event envelopes and expose an event publication capability in EntityExecutionContext. It must not import concrete Entity contracts, daemon registries, transport services, or host code. Concrete Entities and daemon-owned registries may request publication through that generic capability, but the daemon resolves the concrete contract and performs the actual broadcast.

The daemon-owned IPC server is the authoritative connected publication point for live Entity events. Surfaces subscribe through daemon event.subscribe with Entity channel patterns. Browser-hosted Open Mission surfaces receive those daemon notifications through Server-Sent Events. SSE is therefore the browser distribution path for contract-declared Entity events.

Transport-specific streams remain separate contracts. A Terminal WebSocket or PTY transport may carry raw input, resize, output chunks, and live screen material for interactive communication, but it is not the general Entity event system. The same Terminal may also publish contract-declared Entity events such as data.changed and recordingEntry.appended through daemon IPC and SSE.

Terminal Proof Slice

Terminal is the reference Entity for this rule.

  • TerminalContract.events['data.changed'] publishes complete TerminalSchema data when the Terminal Entity boundary state changes.
  • TerminalContract.events['recordingEntry.appended'] publishes the appended TerminalRecordingEntrySchema row for a Terminal-owned raw PTY recording fact.
  • TerminalRecordingEntryContract.events['data.changed'] publishes the individual recording Entity when one is appended.
  • The TerminalRegistry remains responsible for live PTY handles, screen buffers, and low-level transport callbacks, but those callbacks are translated into contract-declared Entity events before crossing the daemon event boundary.
  • Browser surfaces that need Entity event updates receive them through SSE channel subscriptions such as terminal:*.* and terminal_recording_entry:*.*.

Consequences

  • Contracts own event names and payload schemas; registries and transports do not invent public event vocabulary.
  • Event publication is validated at the daemon boundary before broadcast.
  • Entity event subscribers can use one channel grammar across daemon IPC and SSE.
  • Terminal byte-stream communication and Entity data-change events remain separate surfaces.
  • Future Entities can adopt the same publication capability without duplicating daemon socket or SSE logic.

Validation Expectations

Implementation must prove at least:

  • contract-declared event publication rejects undeclared events and invalid payloads;
  • Terminal publishes terminal:<id>.data.changed and terminal:<id>.recordingEntry.appended envelopes through the generic event capability;
  • TerminalRecordingEntry publishes terminal_recording_entry:<id>.data.changed envelopes through the same capability;
  • daemon IPC broadcast receives only contract-validated EntityEventEnvelopeSchema events;
  • browser SSE subscriptions include the relevant Entity channel patterns for public Terminal events.